tutus-chain/pkg/core/native/treasury.go

149 lines
4.7 KiB
Go

package native
import (
"math/big"
"github.com/tutus-one/tutus-chain/pkg/config"
"github.com/tutus-one/tutus-chain/pkg/core/dao"
"github.com/tutus-one/tutus-chain/pkg/core/interop"
"github.com/tutus-one/tutus-chain/pkg/core/native/nativeids"
"github.com/tutus-one/tutus-chain/pkg/core/native/nativenames"
"github.com/tutus-one/tutus-chain/pkg/smartcontract"
"github.com/tutus-one/tutus-chain/pkg/smartcontract/callflag"
"github.com/tutus-one/tutus-chain/pkg/smartcontract/manifest"
"github.com/tutus-one/tutus-chain/pkg/util"
"github.com/tutus-one/tutus-chain/pkg/vm/stackitem"
)
// Treasury represents Treasury native contract.
type Treasury struct {
interop.ContractMD
Tutus ITutus
}
// Storage key prefixes for Treasury.
const (
prefixTreasuryDeficit byte = 0x01 // -> *big.Int (cumulative deficit from fee subsidies)
)
var _ interop.Contract = (*Treasury)(nil)
func newTreasury() *Treasury {
t := &Treasury{
ContractMD: *interop.NewContractMD(nativenames.Treasury, nativeids.Treasury, func(m *manifest.Manifest, hardfork config.Hardfork) {
m.SupportedStandards = []string{manifest.NEP26StandardName, manifest.NEP27StandardName, manifest.NEP30StandardName}
}),
}
defer t.BuildHFSpecificMD(t.ActiveIn())
desc := NewDescriptor("verify", smartcontract.BoolType)
md := NewMethodAndPrice(t.verify, 1<<5, callflag.ReadStates)
t.AddMethod(md, desc)
desc = NewDescriptor("onNEP11Payment", smartcontract.VoidType,
manifest.NewParameter("from", smartcontract.Hash160Type),
manifest.NewParameter("amount", smartcontract.IntegerType),
manifest.NewParameter("tokenId", smartcontract.ByteArrayType),
manifest.NewParameter("data", smartcontract.AnyType))
md = NewMethodAndPrice(t.onNEP11Payment, 1<<5, callflag.NoneFlag)
t.AddMethod(md, desc)
desc = NewDescriptor("onNEP17Payment", smartcontract.VoidType,
manifest.NewParameter("from", smartcontract.Hash160Type),
manifest.NewParameter("amount", smartcontract.IntegerType),
manifest.NewParameter("data", smartcontract.AnyType))
md = NewMethodAndPrice(t.onNEP17Payment, 1<<5, callflag.NoneFlag)
t.AddMethod(md, desc)
return t
}
// OnPersist implements the [interop.Contract] interface.
func (t *Treasury) OnPersist(ic *interop.Context) error {
return nil
}
// PostPersist implements the [interop.Contract] interface.
func (t *Treasury) PostPersist(ic *interop.Context) error {
return nil
}
// Metadata implements the [interop.Contract] interface.
func (t *Treasury) Metadata() *interop.ContractMD {
return &t.ContractMD
}
// Initialize implements the [interop.Contract] interface.
func (t *Treasury) Initialize(ic *interop.Context, hf *config.Hardfork, newMD *interop.HFSpecificContractMD) error {
return nil
}
// InitializeCache implements the [interop.Contract] interface.
func (t *Treasury) InitializeCache(_ interop.IsHardforkEnabled, blockHeight uint32, d *dao.Simple) error {
return nil
}
// ActiveIn implements the [interop.Contract] interface.
func (t *Treasury) ActiveIn() *config.Hardfork {
var f = config.HFFaun
return &f
}
func (t *Treasury) verify(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
return stackitem.NewBool(t.Tutus.CheckCommittee(ic))
}
func (t *Treasury) onNEP11Payment(ic *interop.Context, args []stackitem.Item) stackitem.Item {
// Arguments must be accessed and parsed to match the reference behaviour, but no real action is performed.
from := toUint160(args[0])
amount := toBigInt(args[1])
tokenId := toBytes(args[2])
data := args[3]
var _, _, _, _ = from, amount, tokenId, data
return stackitem.Null{}
}
func (t *Treasury) onNEP17Payment(ic *interop.Context, args []stackitem.Item) stackitem.Item {
// Arguments must be accessed and parsed to match the reference behaviour, but no real action is performed.
from := toUint160(args[0])
amount := toBigInt(args[1])
data := args[2]
var _, _, _ = from, amount, data
return stackitem.Null{}
}
// Public methods for cross-native access
// Address returns the contract's script hash.
func (t *Treasury) Address() util.Uint160 {
return t.Hash
}
// Storage key helpers
func makeDeficitKey() []byte {
return []byte{prefixTreasuryDeficit}
}
// AddDeficit adds to the cumulative deficit (for cross-native access).
// This is called when Treasury cannot cover fee subsidies for Vita holders.
func (t *Treasury) AddDeficit(d *dao.Simple, amount *big.Int) {
if amount.Sign() <= 0 {
return
}
current := t.GetDeficit(d)
newDeficit := new(big.Int).Add(current, amount)
d.PutStorageItem(t.ID, makeDeficitKey(), newDeficit.Bytes())
}
// GetDeficit returns the current cumulative deficit (for cross-native access).
func (t *Treasury) GetDeficit(d *dao.Simple) *big.Int {
si := d.GetStorageItem(t.ID, makeDeficitKey())
if si == nil {
return big.NewInt(0)
}
return new(big.Int).SetBytes(si)
}