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  }