github.com/dim4egster/coreth@v0.10.2/core/vm/contracts_stateful.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package vm 5 6 import ( 7 "fmt" 8 "math/big" 9 10 "github.com/dim4egster/coreth/precompile" 11 "github.com/dim4egster/coreth/vmerrs" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/holiman/uint256" 14 ) 15 16 // PrecompiledContractsApricot contains the default set of pre-compiled Ethereum 17 // contracts used in the Istanbul release and the stateful precompiled contracts 18 // added for the Avalanche Apricot release. 19 // Apricot is incompatible with the YoloV3 Release since it does not include the 20 // BLS12-381 Curve Operations added to the set of precompiled contracts 21 22 var ( 23 genesisContractAddr = common.HexToAddress("0x0100000000000000000000000000000000000000") 24 NativeAssetBalanceAddr = common.HexToAddress("0x0100000000000000000000000000000000000001") 25 NativeAssetCallAddr = common.HexToAddress("0x0100000000000000000000000000000000000002") 26 ) 27 28 // wrappedPrecompiledContract implements StatefulPrecompiledContract by wrapping stateless native precompiled contracts 29 // in Ethereum. 30 type wrappedPrecompiledContract struct { 31 p PrecompiledContract 32 } 33 34 func newWrappedPrecompiledContract(p PrecompiledContract) precompile.StatefulPrecompiledContract { 35 return &wrappedPrecompiledContract{p: p} 36 } 37 38 // Run implements the StatefulPrecompiledContract interface 39 func (w *wrappedPrecompiledContract) Run(accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { 40 return RunPrecompiledContract(w.p, input, suppliedGas) 41 } 42 43 // RunStatefulPrecompiledContract confirms runs [precompile] with the specified parameters. 44 func RunStatefulPrecompiledContract(precompile precompile.StatefulPrecompiledContract, accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { 45 return precompile.Run(accessibleState, caller, addr, input, suppliedGas, readOnly) 46 } 47 48 // nativeAssetBalance is a precompiled contract used to retrieve the native asset balance 49 type nativeAssetBalance struct { 50 gasCost uint64 51 } 52 53 // PackNativeAssetBalanceInput packs the arguments into the required input data for a transaction to be passed into 54 // the native asset balance precompile. 55 func PackNativeAssetBalanceInput(address common.Address, assetID common.Hash) []byte { 56 input := make([]byte, 52) 57 copy(input, address.Bytes()) 58 copy(input[20:], assetID.Bytes()) 59 return input 60 } 61 62 // UnpackNativeAssetBalanceInput attempts to unpack [input] into the arguments to the native asset balance precompile 63 func UnpackNativeAssetBalanceInput(input []byte) (common.Address, common.Hash, error) { 64 if len(input) != 52 { 65 return common.Address{}, common.Hash{}, fmt.Errorf("native asset balance input had unexpcted length %d", len(input)) 66 } 67 address := common.BytesToAddress(input[:20]) 68 assetID := common.Hash{} 69 assetID.SetBytes(input[20:52]) 70 return address, assetID, nil 71 } 72 73 // Run implements StatefulPrecompiledContract 74 func (b *nativeAssetBalance) Run(accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { 75 // input: encodePacked(address 20 bytes, assetID 32 bytes) 76 if suppliedGas < b.gasCost { 77 return nil, 0, vmerrs.ErrOutOfGas 78 } 79 remainingGas = suppliedGas - b.gasCost 80 81 address, assetID, err := UnpackNativeAssetBalanceInput(input) 82 if err != nil { 83 return nil, remainingGas, vmerrs.ErrExecutionReverted 84 } 85 86 res, overflow := uint256.FromBig(accessibleState.GetStateDB().GetBalanceMultiCoin(address, assetID)) 87 if overflow { 88 return nil, remainingGas, vmerrs.ErrExecutionReverted 89 } 90 return common.LeftPadBytes(res.Bytes(), 32), remainingGas, nil 91 } 92 93 // nativeAssetCall atomically transfers a native asset to a recipient address as well as calling that 94 // address 95 type nativeAssetCall struct { 96 gasCost uint64 97 } 98 99 // PackNativeAssetCallInput packs the arguments into the required input data for a transaction to be passed into 100 // the native asset precompile. 101 // Assumes that [assetAmount] is non-nil. 102 func PackNativeAssetCallInput(address common.Address, assetID common.Hash, assetAmount *big.Int, callData []byte) []byte { 103 input := make([]byte, 84+len(callData)) 104 copy(input[0:20], address.Bytes()) 105 copy(input[20:52], assetID.Bytes()) 106 assetAmount.FillBytes(input[52:84]) 107 copy(input[84:], callData) 108 return input 109 } 110 111 // UnpackNativeAssetCallInput attempts to unpack [input] into the arguments to the native asset call precompile 112 func UnpackNativeAssetCallInput(input []byte) (common.Address, common.Hash, *big.Int, []byte, error) { 113 if len(input) < 84 { 114 return common.Address{}, common.Hash{}, nil, nil, fmt.Errorf("native asset call input had unexpected length %d", len(input)) 115 } 116 to := common.BytesToAddress(input[:20]) 117 assetID := common.BytesToHash(input[20:52]) 118 assetAmount := new(big.Int).SetBytes(input[52:84]) 119 callData := input[84:] 120 return to, assetID, assetAmount, callData, nil 121 } 122 123 // Run implements StatefulPrecompiledContract 124 func (c *nativeAssetCall) Run(accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { 125 // input: encodePacked(address 20 bytes, assetID 32 bytes, assetAmount 32 bytes, callData variable length bytes) 126 return accessibleState.NativeAssetCall(caller, input, suppliedGas, c.gasCost, readOnly) 127 } 128 129 type deprecatedContract struct{} 130 131 func (*deprecatedContract) Run(accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) { 132 return nil, suppliedGas, vmerrs.ErrExecutionReverted 133 }