Merge branch 'release/v1.20.0' into raulk/hyperspace-nv20-migration
This commit is contained in:
@@ -628,6 +628,11 @@ workflows:
|
||||
suite: itest-eth_block_hash
|
||||
target: "./itests/eth_block_hash_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_bytecode
|
||||
suite: itest-eth_bytecode
|
||||
target: "./itests/eth_bytecode_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_config
|
||||
suite: itest-eth_config
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
gocrypto "github.com/filecoin-project/go-crypto"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
||||
@@ -97,24 +98,31 @@ func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) {
|
||||
|
||||
func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
var (
|
||||
to *EthAddress
|
||||
params []byte
|
||||
paramsReader = bytes.NewReader(msg.Params)
|
||||
err error
|
||||
to *EthAddress
|
||||
params []byte
|
||||
err error
|
||||
)
|
||||
|
||||
if msg.Version != 0 {
|
||||
return EthTxArgs{}, xerrors.Errorf("unsupported msg version: %d", msg.Version)
|
||||
}
|
||||
|
||||
if len(msg.Params) > 0 {
|
||||
paramsReader := bytes.NewReader(msg.Params)
|
||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||
}
|
||||
if paramsReader.Len() != 0 {
|
||||
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
|
||||
}
|
||||
if len(params) == 0 {
|
||||
return EthTxArgs{}, xerrors.Errorf("non-empty params encode empty byte array")
|
||||
}
|
||||
}
|
||||
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
switch msg.Method {
|
||||
case builtintypes.MethodsEAM.CreateExternal:
|
||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||
}
|
||||
default:
|
||||
if msg.Method != builtintypes.MethodsEAM.CreateExternal {
|
||||
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
|
||||
}
|
||||
} else if msg.Method == builtintypes.MethodsEVM.InvokeContract || msg.Method == builtintypes.MethodSend {
|
||||
@@ -129,23 +137,12 @@ func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
to = &addr
|
||||
|
||||
if len(msg.Params) > 0 {
|
||||
params, err = cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, xerrors.Errorf("failed to read params byte array: %w", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return EthTxArgs{},
|
||||
xerrors.Errorf("invalid methodnum %d: only allowed method is InvokeContract(%d)",
|
||||
msg.Method, builtintypes.MethodsEVM.InvokeContract)
|
||||
}
|
||||
|
||||
if paramsReader.Len() != 0 {
|
||||
return EthTxArgs{}, xerrors.Errorf("extra data found in params")
|
||||
}
|
||||
|
||||
return EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Nonce: int(msg.Nonce),
|
||||
@@ -165,34 +162,26 @@ func (tx *EthTxArgs) ToUnsignedMessage(from address.Address) (*types.Message, er
|
||||
|
||||
var err error
|
||||
var params []byte
|
||||
var to address.Address
|
||||
method := builtintypes.MethodsEVM.InvokeContract
|
||||
// nil indicates the EAM, only CreateExternal is allowed
|
||||
if tx.To == nil {
|
||||
to = builtintypes.EthereumAddressManagerActorAddr
|
||||
method = builtintypes.MethodsEAM.CreateExternal
|
||||
if len(tx.Input) == 0 {
|
||||
return nil, xerrors.New("cannot call CreateExternal without params")
|
||||
}
|
||||
|
||||
if len(tx.Input) > 0 {
|
||||
buf := new(bytes.Buffer)
|
||||
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
||||
return nil, xerrors.Errorf("failed to serialize Create params: %w", err)
|
||||
return nil, xerrors.Errorf("failed to write input args: %w", err)
|
||||
}
|
||||
|
||||
params = buf.Bytes()
|
||||
}
|
||||
|
||||
var to address.Address
|
||||
var method abi.MethodNum
|
||||
// nil indicates the EAM, only CreateExternal is allowed
|
||||
if tx.To == nil {
|
||||
method = builtintypes.MethodsEAM.CreateExternal
|
||||
to = builtintypes.EthereumAddressManagerActorAddr
|
||||
} else {
|
||||
method = builtintypes.MethodsEVM.InvokeContract
|
||||
to, err = tx.To.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to convert To into filecoin addr: %w", err)
|
||||
}
|
||||
if len(tx.Input) > 0 {
|
||||
buf := new(bytes.Buffer)
|
||||
if err = cbg.WriteByteArray(buf, tx.Input); err != nil {
|
||||
return nil, xerrors.Errorf("failed to write input args: %w", err)
|
||||
}
|
||||
params = buf.Bytes()
|
||||
}
|
||||
}
|
||||
|
||||
return &types.Message{
|
||||
|
||||
@@ -44,7 +44,7 @@ require (
|
||||
github.com/filecoin-project/go-legs v0.4.4
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.4
|
||||
github.com/filecoin-project/go-state-types v0.10.0-alpha-9.0.20230213153831-59a688c56a0a
|
||||
github.com/filecoin-project/go-state-types v0.10.0-rc2.0.20230213183937-7f1ede218b87
|
||||
github.com/filecoin-project/go-statemachine v1.0.2
|
||||
github.com/filecoin-project/go-statestore v0.2.0
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||
@@ -110,7 +110,7 @@ require (
|
||||
github.com/ipld/go-car v0.4.0
|
||||
github.com/ipld/go-car/v2 v2.5.0
|
||||
github.com/ipld/go-codec-dagpb v1.5.0
|
||||
github.com/ipld/go-ipld-prime v0.18.0
|
||||
github.com/ipld/go-ipld-prime v0.20.0
|
||||
github.com/ipld/go-ipld-selector-text-lite v0.0.1
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/koalacxr/quantile v0.0.1
|
||||
@@ -133,7 +133,7 @@ require (
|
||||
github.com/multiformats/go-multiaddr v0.7.0
|
||||
github.com/multiformats/go-multiaddr-dns v0.3.1
|
||||
github.com/multiformats/go-multibase v0.1.1
|
||||
github.com/multiformats/go-multicodec v0.6.0
|
||||
github.com/multiformats/go-multicodec v0.8.0
|
||||
github.com/multiformats/go-multihash v0.2.1
|
||||
github.com/multiformats/go-varint v0.0.6
|
||||
github.com/open-rpc/meta-schema v0.0.0-20201029221707-1b72ef2ea333
|
||||
|
||||
@@ -356,8 +356,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS
|
||||
github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.10.0-alpha-9.0.20230213153831-59a688c56a0a h1:j0SLWenP9dTKQtRDmxCPjnMNGxbcgnPHi0EyMDCTRaM=
|
||||
github.com/filecoin-project/go-state-types v0.10.0-alpha-9.0.20230213153831-59a688c56a0a/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024=
|
||||
github.com/filecoin-project/go-state-types v0.10.0-rc2.0.20230213183937-7f1ede218b87 h1:gqKaMwXp8mrvf1Zj+l8mXUPTC2HYf+TG7rcSivO0nDI=
|
||||
github.com/filecoin-project/go-state-types v0.10.0-rc2.0.20230213183937-7f1ede218b87/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=
|
||||
@@ -403,8 +403,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
|
||||
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
@@ -899,8 +899,8 @@ github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHt
|
||||
github.com/ipld/go-ipld-prime v0.14.0/go.mod h1:9ASQLwUFLptCov6lIYc70GRB4V7UTyLD0IJtrDJe6ZM=
|
||||
github.com/ipld/go-ipld-prime v0.16.0/go.mod h1:axSCuOCBPqrH+gvXr2w9uAOulJqBPhHPT2PjoiiU1qA=
|
||||
github.com/ipld/go-ipld-prime v0.17.0/go.mod h1:aYcKm5TIvGfY8P3QBKz/2gKcLxzJ1zDaD+o0bOowhgs=
|
||||
github.com/ipld/go-ipld-prime v0.18.0 h1:xUk7NUBSWHEXdjiOu2sLXouFJOMs0yoYzeI5RAqhYQo=
|
||||
github.com/ipld/go-ipld-prime v0.18.0/go.mod h1:735yXW548CKrLwVCYXzqx90p5deRJMVVxM9eJ4Qe+qE=
|
||||
github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
|
||||
github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
|
||||
github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU=
|
||||
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73 h1:TsyATB2ZRRQGTwafJdgEUQkmjOExRV0DNokcihZxbnQ=
|
||||
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY=
|
||||
@@ -997,8 +997,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
@@ -1523,8 +1523,8 @@ github.com/multiformats/go-multicodec v0.3.1-0.20210902112759-1539a079fd61/go.mo
|
||||
github.com/multiformats/go-multicodec v0.3.1-0.20211210143421-a526f306ed2c/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
|
||||
github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ=
|
||||
github.com/multiformats/go-multicodec v0.5.0/go.mod h1:DiY2HFaEp5EhEXb/iYzVAunmyX/aSFMxq2KMKfWEues=
|
||||
github.com/multiformats/go-multicodec v0.6.0 h1:KhH2kSuCARyuJraYMFxrNO3DqIaYhOdS039kbhgVwpE=
|
||||
github.com/multiformats/go-multicodec v0.6.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw=
|
||||
github.com/multiformats/go-multicodec v0.8.0 h1:evBmgkbSQux+Ds2IgfhkO38Dl2GDtRW8/Rp6YiSHX/Q=
|
||||
github.com/multiformats/go-multicodec v0.8.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw=
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
|
||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
@@ -1708,7 +1708,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
@@ -1849,8 +1849,8 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
|
||||
github.com/warpfork/go-testmark v0.10.0 h1:E86YlUMYfwIacEsQGlnTvjk1IgYkyTGjPhF0RnwTCmw=
|
||||
github.com/warpfork/go-testmark v0.10.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
|
||||
github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U=
|
||||
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w=
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,590 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
abstract contract Initializable {
|
||||
uint8 private _initialized;
|
||||
|
||||
bool private _initializing;
|
||||
|
||||
event Initialized(uint8 version);
|
||||
|
||||
modifier initializer() {
|
||||
bool isTopLevelCall = !_initializing;
|
||||
require(
|
||||
(isTopLevelCall && _initialized < 1) ||
|
||||
(!Address.isContract(address(this)) && _initialized == 1),
|
||||
"Initializable: contract is already initialized"
|
||||
);
|
||||
_initialized = 1;
|
||||
if (isTopLevelCall) {
|
||||
_initializing = true;
|
||||
}
|
||||
_;
|
||||
if (isTopLevelCall) {
|
||||
_initializing = false;
|
||||
emit Initialized(1);
|
||||
}
|
||||
}
|
||||
|
||||
modifier reinitializer(uint8 version) {
|
||||
require(
|
||||
!_initializing && _initialized < version,
|
||||
"Initializable: contract is already initialized"
|
||||
);
|
||||
_initialized = version;
|
||||
_initializing = true;
|
||||
_;
|
||||
_initializing = false;
|
||||
emit Initialized(version);
|
||||
}
|
||||
|
||||
modifier onlyInitializing() {
|
||||
require(_initializing, "Initializable: contract is not initializing");
|
||||
_;
|
||||
}
|
||||
|
||||
function _disableInitializers() internal virtual {
|
||||
require(!_initializing, "Initializable: contract is initializing");
|
||||
if (_initialized != type(uint8).max) {
|
||||
_initialized = type(uint8).max;
|
||||
emit Initialized(type(uint8).max);
|
||||
}
|
||||
}
|
||||
|
||||
function _getInitializedVersion() internal view returns (uint8) {
|
||||
return _initialized;
|
||||
}
|
||||
|
||||
function _isInitializing() internal view returns (bool) {
|
||||
return _initializing;
|
||||
}
|
||||
}
|
||||
|
||||
contract Implementation4 is Initializable {
|
||||
uint256 internal _value;
|
||||
|
||||
function initialize() public initializer {}
|
||||
|
||||
function setValue(uint256 _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
|
||||
function getValue() public view returns (uint256) {
|
||||
return _value;
|
||||
}
|
||||
|
||||
fallback() external {
|
||||
_value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
contract Implementation2 is Initializable {
|
||||
uint256 internal _value;
|
||||
|
||||
function initialize() public initializer {}
|
||||
|
||||
function setValue(uint256 _number) public {
|
||||
_value = _number;
|
||||
}
|
||||
|
||||
function getValue() public view returns (uint256) {
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
abstract contract Proxy {
|
||||
function _delegate(address implementation) internal virtual {
|
||||
assembly {
|
||||
calldatacopy(0, 0, calldatasize())
|
||||
|
||||
let result := delegatecall(
|
||||
gas(),
|
||||
implementation,
|
||||
0,
|
||||
calldatasize(),
|
||||
0,
|
||||
0
|
||||
)
|
||||
|
||||
returndatacopy(0, 0, returndatasize())
|
||||
|
||||
switch result
|
||||
case 0 {
|
||||
revert(0, returndatasize())
|
||||
}
|
||||
default {
|
||||
return(0, returndatasize())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _implementation() internal view virtual returns (address);
|
||||
|
||||
function _fallback() internal virtual {
|
||||
_beforeFallback();
|
||||
_delegate(_implementation());
|
||||
}
|
||||
|
||||
fallback() external payable virtual {
|
||||
_fallback();
|
||||
}
|
||||
|
||||
receive() external payable virtual {
|
||||
_fallback();
|
||||
}
|
||||
|
||||
function _beforeFallback() internal virtual {}
|
||||
}
|
||||
|
||||
interface IBeacon {
|
||||
function implementation() external view returns (address);
|
||||
}
|
||||
|
||||
interface IERC1822Proxiable {
|
||||
function proxiableUUID() external view returns (bytes32);
|
||||
}
|
||||
|
||||
library Address {
|
||||
function isContract(address account) internal view returns (bool) {
|
||||
return account.code.length > 0;
|
||||
}
|
||||
|
||||
function sendValue(address payable recipient, uint256 amount) internal {
|
||||
require(
|
||||
address(this).balance >= amount,
|
||||
"Address: insufficient balance"
|
||||
);
|
||||
|
||||
(bool success, ) = recipient.call{value: amount}("");
|
||||
require(
|
||||
success,
|
||||
"Address: unable to send value, recipient may have reverted"
|
||||
);
|
||||
}
|
||||
|
||||
function functionCall(
|
||||
address target,
|
||||
bytes memory data
|
||||
) internal returns (bytes memory) {
|
||||
return
|
||||
functionCallWithValue(
|
||||
target,
|
||||
data,
|
||||
0,
|
||||
"Address: low-level call failed"
|
||||
);
|
||||
}
|
||||
|
||||
function functionCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
return functionCallWithValue(target, data, 0, errorMessage);
|
||||
}
|
||||
|
||||
function functionCallWithValue(
|
||||
address target,
|
||||
bytes memory data,
|
||||
uint256 value
|
||||
) internal returns (bytes memory) {
|
||||
return
|
||||
functionCallWithValue(
|
||||
target,
|
||||
data,
|
||||
value,
|
||||
"Address: low-level call with value failed"
|
||||
);
|
||||
}
|
||||
|
||||
function functionCallWithValue(
|
||||
address target,
|
||||
bytes memory data,
|
||||
uint256 value,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
require(
|
||||
address(this).balance >= value,
|
||||
"Address: insufficient balance for call"
|
||||
);
|
||||
(bool success, bytes memory returndata) = target.call{value: value}(
|
||||
data
|
||||
);
|
||||
return
|
||||
verifyCallResultFromTarget(
|
||||
target,
|
||||
success,
|
||||
returndata,
|
||||
errorMessage
|
||||
);
|
||||
}
|
||||
|
||||
function functionStaticCall(
|
||||
address target,
|
||||
bytes memory data
|
||||
) internal view returns (bytes memory) {
|
||||
return
|
||||
functionStaticCall(
|
||||
target,
|
||||
data,
|
||||
"Address: low-level static call failed"
|
||||
);
|
||||
}
|
||||
|
||||
function functionStaticCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal view returns (bytes memory) {
|
||||
(bool success, bytes memory returndata) = target.staticcall(data);
|
||||
return
|
||||
verifyCallResultFromTarget(
|
||||
target,
|
||||
success,
|
||||
returndata,
|
||||
errorMessage
|
||||
);
|
||||
}
|
||||
|
||||
function functionDelegateCall(
|
||||
address target,
|
||||
bytes memory data
|
||||
) internal returns (bytes memory) {
|
||||
return
|
||||
functionDelegateCall(
|
||||
target,
|
||||
data,
|
||||
"Address: low-level delegate call failed"
|
||||
);
|
||||
}
|
||||
|
||||
function functionDelegateCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
(bool success, bytes memory returndata) = target.delegatecall(data);
|
||||
return
|
||||
verifyCallResultFromTarget(
|
||||
target,
|
||||
success,
|
||||
returndata,
|
||||
errorMessage
|
||||
);
|
||||
}
|
||||
|
||||
function verifyCallResultFromTarget(
|
||||
address target,
|
||||
bool success,
|
||||
bytes memory returndata,
|
||||
string memory errorMessage
|
||||
) internal view returns (bytes memory) {
|
||||
if (success) {
|
||||
if (returndata.length == 0) {
|
||||
require(isContract(target), "Address: call to non-contract");
|
||||
}
|
||||
return returndata;
|
||||
} else {
|
||||
_revert(returndata, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function verifyCallResult(
|
||||
bool success,
|
||||
bytes memory returndata,
|
||||
string memory errorMessage
|
||||
) internal pure returns (bytes memory) {
|
||||
if (success) {
|
||||
return returndata;
|
||||
} else {
|
||||
_revert(returndata, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function _revert(
|
||||
bytes memory returndata,
|
||||
string memory errorMessage
|
||||
) private pure {
|
||||
if (returndata.length > 0) {
|
||||
assembly {
|
||||
let returndata_size := mload(returndata)
|
||||
revert(add(32, returndata), returndata_size)
|
||||
}
|
||||
} else {
|
||||
revert(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
library StorageSlot {
|
||||
struct AddressSlot {
|
||||
address value;
|
||||
}
|
||||
|
||||
struct BooleanSlot {
|
||||
bool value;
|
||||
}
|
||||
|
||||
struct Bytes32Slot {
|
||||
bytes32 value;
|
||||
}
|
||||
|
||||
struct Uint256Slot {
|
||||
uint256 value;
|
||||
}
|
||||
|
||||
function getAddressSlot(
|
||||
bytes32 slot
|
||||
) internal pure returns (AddressSlot storage r) {
|
||||
assembly {
|
||||
r.slot := slot
|
||||
}
|
||||
}
|
||||
|
||||
function getBooleanSlot(
|
||||
bytes32 slot
|
||||
) internal pure returns (BooleanSlot storage r) {
|
||||
assembly {
|
||||
r.slot := slot
|
||||
}
|
||||
}
|
||||
|
||||
function getBytes32Slot(
|
||||
bytes32 slot
|
||||
) internal pure returns (Bytes32Slot storage r) {
|
||||
assembly {
|
||||
r.slot := slot
|
||||
}
|
||||
}
|
||||
|
||||
function getUint256Slot(
|
||||
bytes32 slot
|
||||
) internal pure returns (Uint256Slot storage r) {
|
||||
assembly {
|
||||
r.slot := slot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract contract ERC1967Upgrade {
|
||||
bytes32 private constant _ROLLBACK_SLOT =
|
||||
0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
|
||||
|
||||
bytes32 internal constant _IMPLEMENTATION_SLOT =
|
||||
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
|
||||
|
||||
event Upgraded(address indexed implementation);
|
||||
|
||||
function _getImplementation() internal view returns (address) {
|
||||
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
|
||||
}
|
||||
|
||||
function _setImplementation(address newImplementation) private {
|
||||
require(
|
||||
Address.isContract(newImplementation),
|
||||
"ERC1967: new implementation is not a contract"
|
||||
);
|
||||
StorageSlot
|
||||
.getAddressSlot(_IMPLEMENTATION_SLOT)
|
||||
.value = newImplementation;
|
||||
}
|
||||
|
||||
function _upgradeTo(address newImplementation) internal {
|
||||
_setImplementation(newImplementation);
|
||||
emit Upgraded(newImplementation);
|
||||
}
|
||||
|
||||
function _upgradeToAndCall(
|
||||
address newImplementation,
|
||||
bytes memory data,
|
||||
bool forceCall
|
||||
) internal {
|
||||
_upgradeTo(newImplementation);
|
||||
if (data.length > 0 || forceCall) {
|
||||
Address.functionDelegateCall(newImplementation, data);
|
||||
}
|
||||
}
|
||||
|
||||
function _upgradeToAndCallUUPS(
|
||||
address newImplementation,
|
||||
bytes memory data,
|
||||
bool forceCall
|
||||
) internal {
|
||||
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
|
||||
_setImplementation(newImplementation);
|
||||
} else {
|
||||
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (
|
||||
bytes32 slot
|
||||
) {
|
||||
require(
|
||||
slot == _IMPLEMENTATION_SLOT,
|
||||
"ERC1967Upgrade: unsupported proxiableUUID"
|
||||
);
|
||||
} catch {
|
||||
revert("ERC1967Upgrade: new implementation is not UUPS");
|
||||
}
|
||||
_upgradeToAndCall(newImplementation, data, forceCall);
|
||||
}
|
||||
}
|
||||
|
||||
bytes32 internal constant _ADMIN_SLOT =
|
||||
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
|
||||
|
||||
event AdminChanged(address previousAdmin, address newAdmin);
|
||||
|
||||
function _getAdmin() internal view returns (address) {
|
||||
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
|
||||
}
|
||||
|
||||
function _setAdmin(address newAdmin) private {
|
||||
require(
|
||||
newAdmin != address(0),
|
||||
"ERC1967: new admin is the zero address"
|
||||
);
|
||||
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
|
||||
}
|
||||
|
||||
function _changeAdmin(address newAdmin) internal {
|
||||
emit AdminChanged(_getAdmin(), newAdmin);
|
||||
_setAdmin(newAdmin);
|
||||
}
|
||||
|
||||
bytes32 internal constant _BEACON_SLOT =
|
||||
0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
|
||||
|
||||
event BeaconUpgraded(address indexed beacon);
|
||||
|
||||
function _getBeacon() internal view returns (address) {
|
||||
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
|
||||
}
|
||||
|
||||
function _setBeacon(address newBeacon) private {
|
||||
require(
|
||||
Address.isContract(newBeacon),
|
||||
"ERC1967: new beacon is not a contract"
|
||||
);
|
||||
require(
|
||||
Address.isContract(IBeacon(newBeacon).implementation()),
|
||||
"ERC1967: beacon implementation is not a contract"
|
||||
);
|
||||
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
|
||||
}
|
||||
|
||||
function _upgradeBeaconToAndCall(
|
||||
address newBeacon,
|
||||
bytes memory data,
|
||||
bool forceCall
|
||||
) internal {
|
||||
_setBeacon(newBeacon);
|
||||
emit BeaconUpgraded(newBeacon);
|
||||
if (data.length > 0 || forceCall) {
|
||||
Address.functionDelegateCall(
|
||||
IBeacon(newBeacon).implementation(),
|
||||
data
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
|
||||
constructor(address _logic, bytes memory _data) payable {
|
||||
_upgradeToAndCall(_logic, _data, false);
|
||||
}
|
||||
|
||||
function _implementation()
|
||||
internal
|
||||
view
|
||||
virtual
|
||||
override
|
||||
returns (address impl)
|
||||
{
|
||||
return ERC1967Upgrade._getImplementation();
|
||||
}
|
||||
}
|
||||
|
||||
contract TransparentUpgradeableProxy is ERC1967Proxy {
|
||||
constructor(address _logic) payable ERC1967Proxy(_logic, "") {
|
||||
_changeAdmin(msg.sender);
|
||||
}
|
||||
|
||||
modifier ifAdmin() {
|
||||
if (msg.sender == _getAdmin()) {
|
||||
_;
|
||||
} else {
|
||||
_fallback();
|
||||
}
|
||||
}
|
||||
|
||||
function admin() external payable ifAdmin returns (address admin_) {
|
||||
_requireZeroValue();
|
||||
admin_ = _getAdmin();
|
||||
}
|
||||
|
||||
function implementation()
|
||||
external
|
||||
payable
|
||||
ifAdmin
|
||||
returns (address implementation_)
|
||||
{
|
||||
_requireZeroValue();
|
||||
implementation_ = _implementation();
|
||||
}
|
||||
|
||||
function changeAdmin(address newAdmin) external payable virtual ifAdmin {
|
||||
_requireZeroValue();
|
||||
_changeAdmin(newAdmin);
|
||||
}
|
||||
|
||||
function upgradeTo(address newImplementation) external payable ifAdmin {
|
||||
_requireZeroValue();
|
||||
_upgradeToAndCall(newImplementation, bytes(""), false);
|
||||
}
|
||||
|
||||
function upgradeToAndCall(
|
||||
address newImplementation,
|
||||
bytes calldata data
|
||||
) external payable ifAdmin {
|
||||
_upgradeToAndCall(newImplementation, data, true);
|
||||
}
|
||||
|
||||
function _admin() internal view virtual returns (address) {
|
||||
return _getAdmin();
|
||||
}
|
||||
|
||||
function _beforeFallback() internal virtual override {
|
||||
require(
|
||||
msg.sender != _getAdmin(),
|
||||
"TransparentUpgradeableProxy: admin cannot fallback to proxy target"
|
||||
);
|
||||
super._beforeFallback();
|
||||
}
|
||||
|
||||
function _requireZeroValue() private {
|
||||
require(msg.value == 0);
|
||||
}
|
||||
}
|
||||
|
||||
contract TestHelper {
|
||||
function getValue(address proxyAddress) public returns (uint256) {
|
||||
Implementation2 proxyInstance2 = Implementation2(proxyAddress);
|
||||
return proxyInstance2.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
contract TransparentUpgradeableProxyTestRunner {
|
||||
function test() public {
|
||||
assert(0 == getValue());
|
||||
}
|
||||
|
||||
function getValue() public returns (uint256) {
|
||||
Implementation4 instance4 = new Implementation4();
|
||||
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
|
||||
address(instance4)
|
||||
);
|
||||
Implementation2 instance2 = new Implementation2();
|
||||
proxy.upgradeTo(address(instance2));
|
||||
//use helper because proxy admin can't call getValue()
|
||||
TestHelper h = new TestHelper();
|
||||
return h.getValue(address(proxy));
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ set -o pipefail
|
||||
# to compile all of the .sol files to their corresponding evm binary files stored as .hex
|
||||
# solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line
|
||||
|
||||
find . -name \*.sol -print0 |
|
||||
find . -maxdepth 1 -name \*.sol -print0 |
|
||||
xargs -0 -I{} bash -euc -o pipefail 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)'
|
||||
|
||||
|
||||
@@ -17,3 +17,7 @@ for filename in Constructor TestApp ValueSender Create2Factory DeployValueTest;
|
||||
solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex
|
||||
done
|
||||
|
||||
for filename in TransparentUpgradeableProxy ; do
|
||||
echo $filename
|
||||
solc --bin $filename.sol | tail -n1| tr -d "\n" > $filename.hex
|
||||
done
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
// TestGetCode ensures that GetCode returns the correct results for:
|
||||
// 1. Placeholders.
|
||||
// 2. Non-existent actors.
|
||||
// 3. Normal EVM actors.
|
||||
// 4. Self-destructed EVM actors.
|
||||
func TestGetCode(t *testing.T) {
|
||||
kit.QuietMiningLogs()
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// Accounts should have empty code.
|
||||
{
|
||||
// A random eth address should have no code.
|
||||
_, ethAddr, filAddr := client.EVM().NewAccount()
|
||||
bytecode, err := client.EVM().EthGetCode(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, bytecode)
|
||||
|
||||
// send some funds to the account.
|
||||
kit.SendFunds(ctx, t, client, filAddr, types.FromFil(10))
|
||||
|
||||
// The code should still be empty, target is now a placeholder.
|
||||
bytecode, err = client.EVM().EthGetCode(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, bytecode)
|
||||
}
|
||||
|
||||
// Check contract code.
|
||||
{
|
||||
// install a contract
|
||||
contractHex, err := os.ReadFile("./contracts/SelfDestruct.hex")
|
||||
require.NoError(t, err)
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
createReturn := client.EVM().DeployContract(ctx, client.DefaultKey.Address, contract)
|
||||
contractAddr := createReturn.EthAddress
|
||||
contractFilAddr := *createReturn.RobustAddress
|
||||
|
||||
// The newly deployed contract should not be empty.
|
||||
bytecode, err := client.EVM().EthGetCode(ctx, contractAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, bytecode)
|
||||
|
||||
// Destroy it.
|
||||
_, _, err = client.EVM().InvokeContractByFuncName(ctx, client.DefaultKey.Address, contractFilAddr, "destroy()", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// The code should be empty again.
|
||||
bytecode, err = client.EVM().EthGetCode(ctx, contractAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, bytecode)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -843,3 +843,15 @@ func TestFEVMBareTransferTriggersSmartContractLogic(t *testing.T) {
|
||||
// The receive() function emits one log, that's how we know we hit it.
|
||||
require.Len(t, receipt.Logs, 1)
|
||||
}
|
||||
|
||||
func TestFEVMProxyUpgradeable(t *testing.T) {
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install transparently upgradeable proxy
|
||||
proxyFilename := "contracts/TransparentUpgradeableProxy.hex"
|
||||
fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, proxyFilename)
|
||||
|
||||
_, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "test()", []byte{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
+2
-2
@@ -63,7 +63,7 @@ func (e *EVM) DeployContractWithValue(ctx context.Context, sender address.Addres
|
||||
require.NoError(err)
|
||||
|
||||
e.t.Log("waiting for message to execute")
|
||||
wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
|
||||
wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 3, 0, false)
|
||||
require.NoError(err)
|
||||
|
||||
require.True(wait.Receipt.ExitCode.IsSuccess(), "contract installation failed")
|
||||
@@ -127,7 +127,7 @@ func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target
|
||||
}
|
||||
|
||||
e.t.Log("waiting for message to execute")
|
||||
wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
|
||||
wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 3, 0, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+44
-39
@@ -427,22 +427,6 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
||||
}
|
||||
|
||||
// use the system actor as the caller
|
||||
from, err := address.NewIDAddress(0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to construct system sender address: %w", err)
|
||||
}
|
||||
msg := &types.Message{
|
||||
From: from,
|
||||
To: to,
|
||||
Value: big.Zero(),
|
||||
Method: builtintypes.MethodsEVM.GetBytecode,
|
||||
Params: nil,
|
||||
GasLimit: build.BlockGasLimit,
|
||||
GasFeeCap: big.Zero(),
|
||||
GasPremium: big.Zero(),
|
||||
}
|
||||
|
||||
ts, err := a.parseBlkParam(ctx, blkParam)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
@@ -453,6 +437,31 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
return nil, xerrors.Errorf("block param must not specify genesis block")
|
||||
}
|
||||
|
||||
actor, err := a.StateManager.LoadActor(ctx, to, ts)
|
||||
if err != nil {
|
||||
if xerrors.Is(err, types.ErrActorNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, xerrors.Errorf("failed to lookup contract %s: %w", ethAddr, err)
|
||||
}
|
||||
|
||||
// Not a contract. We could try to distinguish between accounts and "native" contracts here,
|
||||
// but it's not worth it.
|
||||
if !builtinactors.IsEvmActor(actor.Code) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
From: builtinactors.SystemActorAddr,
|
||||
To: to,
|
||||
Value: big.Zero(),
|
||||
Method: builtintypes.MethodsEVM.GetBytecode,
|
||||
Params: nil,
|
||||
GasLimit: build.BlockGasLimit,
|
||||
GasFeeCap: big.Zero(),
|
||||
GasPremium: big.Zero(),
|
||||
}
|
||||
|
||||
// Try calling until we find a height with no migration.
|
||||
var res *api.InvocResult
|
||||
for {
|
||||
@@ -467,9 +476,7 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// if the call resulted in error, this is not an EVM smart contract;
|
||||
// return no bytecode.
|
||||
return nil, nil
|
||||
return nil, xerrors.Errorf("failed to call GetBytecode: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct == nil {
|
||||
@@ -477,15 +484,20 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode.IsError() {
|
||||
return nil, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error)
|
||||
return nil, xerrors.Errorf("GetBytecode failed: %s", res.Error)
|
||||
}
|
||||
|
||||
var bytecodeCid cbg.CborCid
|
||||
if err := bytecodeCid.UnmarshalCBOR(bytes.NewReader(res.MsgRct.Return)); err != nil {
|
||||
var getBytecodeReturn evm.GetBytecodeReturn
|
||||
if err := getBytecodeReturn.UnmarshalCBOR(bytes.NewReader(res.MsgRct.Return)); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode EVM bytecode CID: %w", err)
|
||||
}
|
||||
|
||||
blk, err := a.Chain.StateBlockstore().Get(ctx, cid.Cid(bytecodeCid))
|
||||
// The contract has selfdestructed, so the code is "empty".
|
||||
if getBytecodeReturn.Cid == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
blk, err := a.Chain.StateBlockstore().Get(ctx, *getBytecodeReturn.Cid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get EVM bytecode: %w", err)
|
||||
}
|
||||
@@ -740,18 +752,20 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.Et
|
||||
}
|
||||
|
||||
var params []byte
|
||||
if len(tx.Data) > 0 {
|
||||
initcode := abi.CborBytes(tx.Data)
|
||||
params2, err := actors.SerializeParams(&initcode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize params: %w", err)
|
||||
}
|
||||
params = params2
|
||||
}
|
||||
|
||||
var to address.Address
|
||||
var method abi.MethodNum
|
||||
if tx.To == nil {
|
||||
// this is a contract creation
|
||||
to = builtintypes.EthereumAddressManagerActorAddr
|
||||
|
||||
initcode := abi.CborBytes(tx.Data)
|
||||
params2, err := actors.SerializeParams(&initcode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize Create params: %w", err)
|
||||
}
|
||||
params = params2
|
||||
method = builtintypes.MethodsEAM.CreateExternal
|
||||
} else {
|
||||
addr, err := tx.To.ToFilecoinAddress()
|
||||
@@ -759,15 +773,6 @@ func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.Et
|
||||
return nil, xerrors.Errorf("cannot get Filecoin address: %w", err)
|
||||
}
|
||||
to = addr
|
||||
|
||||
if len(tx.Data) > 0 {
|
||||
var buf bytes.Buffer
|
||||
if err := cbg.WriteByteArray(&buf, tx.Data); err != nil {
|
||||
return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string")
|
||||
}
|
||||
params = buf.Bytes()
|
||||
}
|
||||
|
||||
method = builtintypes.MethodsEVM.InvokeContract
|
||||
|
||||
// < nv20 (Hyperspace): reset method to MethodSend if no params.
|
||||
|
||||
Reference in New Issue
Block a user