149 lines
4.7 KiB
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
|
|
Annos IAnnos
|
|
}
|
|
|
|
// 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.Annos.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)
|
|
}
|