diff --git a/contract/compile.sh b/contract/compile.sh index e3264afc..c10a6e38 100755 --- a/contract/compile.sh +++ b/contract/compile.sh @@ -31,7 +31,7 @@ echo "===> Compiling contracts" [[ ! -d "$project_dir/contract/artifacts" ]] && mkdir -p "$project_dir/contract/artifacts" contracts=(WFXUpgradable FIP20Upgradable IStaking IError ERC1967Proxy) -contracts+=(IFxBridgeLogic IBridgeCallback ICrosschain) +contracts+=(IFxBridgeLogic IBridgeCallContext ICrosschain) contracts+=(BridgeFeeQuote BridgeFeeOracle BridgeProxy) contracts+=(CrosschainTest StakingTest ERC721TokenTest) diff --git a/contract/contract.go b/contract/contract.go index 5c048ee0..6ab02be0 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -70,9 +70,9 @@ var ( Code: []byte{}, } - fxBridgeABI = MustABIJson(IFxBridgeLogicMetaData.ABI) - bridgeCallbackABI = MustABIJson(IBridgeCallbackMetaData.ABI) - errorABI = MustABIJson(IErrorMetaData.ABI) + fxBridgeABI = MustABIJson(IFxBridgeLogicMetaData.ABI) + bridgeCallContextABI = MustABIJson(IBridgeCallContextMetaData.ABI) + errorABI = MustABIJson(IErrorMetaData.ABI) ) type Caller interface { @@ -136,8 +136,8 @@ func PackRetErrV2(err error) ([]byte, error) { return pack, err } -func PackBridgeCallback(sender, receiver common.Address, tokens []common.Address, amounts []*big.Int, data, memo []byte) ([]byte, error) { - return bridgeCallbackABI.Pack("bridgeCallback", +func PackOnBridgeCall(sender, receiver common.Address, tokens []common.Address, amounts []*big.Int, data, memo []byte) ([]byte, error) { + return bridgeCallContextABI.Pack("onBridgeCall", sender, receiver, tokens, diff --git a/contract/contract_test.go b/contract/contract_test.go index 98e81c91..d1a574ff 100644 --- a/contract/contract_test.go +++ b/contract/contract_test.go @@ -48,13 +48,13 @@ func TestPackBridgeCallback(t *testing.T) { // memo string memo: common.Hex2Bytes("6d656d6f00000000000000000000000000000000000000000000000000000000"), }, - expected: "139975660000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006423b872dd000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206d656d6f00000000000000000000000000000000000000000000000000000000", + expected: "57ffc0920000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006423b872dd000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000206d656d6f00000000000000000000000000000000000000000000000000000000", err: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result, err := contract.PackBridgeCallback(tt.args.sender, tt.args.receiver, tt.args._tokens, tt.args._amounts, tt.args.data, tt.args.memo) + result, err := contract.PackOnBridgeCall(tt.args.sender, tt.args.receiver, tt.args._tokens, tt.args._amounts, tt.args.data, tt.args.memo) if tt.err != nil { require.Error(t, err) require.EqualValues(t, tt.err.Error(), err.Error()) diff --git a/contract/ibridge_call_context.sol.go b/contract/ibridge_call_context.sol.go new file mode 100644 index 00000000..fe0dab30 --- /dev/null +++ b/contract/ibridge_call_context.sol.go @@ -0,0 +1,223 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contract + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IBridgeCallContextMetaData contains all meta data concerning the IBridgeCallContext contract. +var IBridgeCallContextMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_refund\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_memo\",\"type\":\"bytes\"}],\"name\":\"onBridgeCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_msg\",\"type\":\"bytes\"}],\"name\":\"onRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +// IBridgeCallContextABI is the input ABI used to generate the binding from. +// Deprecated: Use IBridgeCallContextMetaData.ABI instead. +var IBridgeCallContextABI = IBridgeCallContextMetaData.ABI + +// IBridgeCallContext is an auto generated Go binding around an Ethereum contract. +type IBridgeCallContext struct { + IBridgeCallContextCaller // Read-only binding to the contract + IBridgeCallContextTransactor // Write-only binding to the contract + IBridgeCallContextFilterer // Log filterer for contract events +} + +// IBridgeCallContextCaller is an auto generated read-only Go binding around an Ethereum contract. +type IBridgeCallContextCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IBridgeCallContextTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IBridgeCallContextTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IBridgeCallContextFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IBridgeCallContextFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IBridgeCallContextSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IBridgeCallContextSession struct { + Contract *IBridgeCallContext // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IBridgeCallContextCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IBridgeCallContextCallerSession struct { + Contract *IBridgeCallContextCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IBridgeCallContextTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IBridgeCallContextTransactorSession struct { + Contract *IBridgeCallContextTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IBridgeCallContextRaw is an auto generated low-level Go binding around an Ethereum contract. +type IBridgeCallContextRaw struct { + Contract *IBridgeCallContext // Generic contract binding to access the raw methods on +} + +// IBridgeCallContextCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IBridgeCallContextCallerRaw struct { + Contract *IBridgeCallContextCaller // Generic read-only contract binding to access the raw methods on +} + +// IBridgeCallContextTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IBridgeCallContextTransactorRaw struct { + Contract *IBridgeCallContextTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIBridgeCallContext creates a new instance of IBridgeCallContext, bound to a specific deployed contract. +func NewIBridgeCallContext(address common.Address, backend bind.ContractBackend) (*IBridgeCallContext, error) { + contract, err := bindIBridgeCallContext(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &IBridgeCallContext{IBridgeCallContextCaller: IBridgeCallContextCaller{contract: contract}, IBridgeCallContextTransactor: IBridgeCallContextTransactor{contract: contract}, IBridgeCallContextFilterer: IBridgeCallContextFilterer{contract: contract}}, nil +} + +// NewIBridgeCallContextCaller creates a new read-only instance of IBridgeCallContext, bound to a specific deployed contract. +func NewIBridgeCallContextCaller(address common.Address, caller bind.ContractCaller) (*IBridgeCallContextCaller, error) { + contract, err := bindIBridgeCallContext(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IBridgeCallContextCaller{contract: contract}, nil +} + +// NewIBridgeCallContextTransactor creates a new write-only instance of IBridgeCallContext, bound to a specific deployed contract. +func NewIBridgeCallContextTransactor(address common.Address, transactor bind.ContractTransactor) (*IBridgeCallContextTransactor, error) { + contract, err := bindIBridgeCallContext(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IBridgeCallContextTransactor{contract: contract}, nil +} + +// NewIBridgeCallContextFilterer creates a new log filterer instance of IBridgeCallContext, bound to a specific deployed contract. +func NewIBridgeCallContextFilterer(address common.Address, filterer bind.ContractFilterer) (*IBridgeCallContextFilterer, error) { + contract, err := bindIBridgeCallContext(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IBridgeCallContextFilterer{contract: contract}, nil +} + +// bindIBridgeCallContext binds a generic wrapper to an already deployed contract. +func bindIBridgeCallContext(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IBridgeCallContextMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IBridgeCallContext *IBridgeCallContextRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IBridgeCallContext.Contract.IBridgeCallContextCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IBridgeCallContext *IBridgeCallContextRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.IBridgeCallContextTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IBridgeCallContext *IBridgeCallContextRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.IBridgeCallContextTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_IBridgeCallContext *IBridgeCallContextCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _IBridgeCallContext.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_IBridgeCallContext *IBridgeCallContextTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_IBridgeCallContext *IBridgeCallContextTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.contract.Transact(opts, method, params...) +} + +// OnBridgeCall is a paid mutator transaction binding the contract method 0x57ffc092. +// +// Solidity: function onBridgeCall(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() +func (_IBridgeCallContext *IBridgeCallContextTransactor) OnBridgeCall(opts *bind.TransactOpts, _sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { + return _IBridgeCallContext.contract.Transact(opts, "onBridgeCall", _sender, _refund, _tokens, _amounts, _data, _memo) +} + +// OnBridgeCall is a paid mutator transaction binding the contract method 0x57ffc092. +// +// Solidity: function onBridgeCall(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() +func (_IBridgeCallContext *IBridgeCallContextSession) OnBridgeCall(_sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.OnBridgeCall(&_IBridgeCallContext.TransactOpts, _sender, _refund, _tokens, _amounts, _data, _memo) +} + +// OnBridgeCall is a paid mutator transaction binding the contract method 0x57ffc092. +// +// Solidity: function onBridgeCall(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() +func (_IBridgeCallContext *IBridgeCallContextTransactorSession) OnBridgeCall(_sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.OnBridgeCall(&_IBridgeCallContext.TransactOpts, _sender, _refund, _tokens, _amounts, _data, _memo) +} + +// OnRevert is a paid mutator transaction binding the contract method 0x8fcaa0b5. +// +// Solidity: function onRevert(bytes _msg) returns() +func (_IBridgeCallContext *IBridgeCallContextTransactor) OnRevert(opts *bind.TransactOpts, _msg []byte) (*types.Transaction, error) { + return _IBridgeCallContext.contract.Transact(opts, "onRevert", _msg) +} + +// OnRevert is a paid mutator transaction binding the contract method 0x8fcaa0b5. +// +// Solidity: function onRevert(bytes _msg) returns() +func (_IBridgeCallContext *IBridgeCallContextSession) OnRevert(_msg []byte) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.OnRevert(&_IBridgeCallContext.TransactOpts, _msg) +} + +// OnRevert is a paid mutator transaction binding the contract method 0x8fcaa0b5. +// +// Solidity: function onRevert(bytes _msg) returns() +func (_IBridgeCallContext *IBridgeCallContextTransactorSession) OnRevert(_msg []byte) (*types.Transaction, error) { + return _IBridgeCallContext.Contract.OnRevert(&_IBridgeCallContext.TransactOpts, _msg) +} diff --git a/contract/ibridge_callback.sol.go b/contract/ibridge_callback.sol.go deleted file mode 100644 index 2985af6c..00000000 --- a/contract/ibridge_callback.sol.go +++ /dev/null @@ -1,202 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package contract - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// IBridgeCallbackMetaData contains all meta data concerning the IBridgeCallback contract. -var IBridgeCallbackMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_refund\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_memo\",\"type\":\"bytes\"}],\"name\":\"bridgeCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", -} - -// IBridgeCallbackABI is the input ABI used to generate the binding from. -// Deprecated: Use IBridgeCallbackMetaData.ABI instead. -var IBridgeCallbackABI = IBridgeCallbackMetaData.ABI - -// IBridgeCallback is an auto generated Go binding around an Ethereum contract. -type IBridgeCallback struct { - IBridgeCallbackCaller // Read-only binding to the contract - IBridgeCallbackTransactor // Write-only binding to the contract - IBridgeCallbackFilterer // Log filterer for contract events -} - -// IBridgeCallbackCaller is an auto generated read-only Go binding around an Ethereum contract. -type IBridgeCallbackCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IBridgeCallbackTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IBridgeCallbackTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IBridgeCallbackFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IBridgeCallbackFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IBridgeCallbackSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type IBridgeCallbackSession struct { - Contract *IBridgeCallback // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IBridgeCallbackCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type IBridgeCallbackCallerSession struct { - Contract *IBridgeCallbackCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// IBridgeCallbackTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type IBridgeCallbackTransactorSession struct { - Contract *IBridgeCallbackTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IBridgeCallbackRaw is an auto generated low-level Go binding around an Ethereum contract. -type IBridgeCallbackRaw struct { - Contract *IBridgeCallback // Generic contract binding to access the raw methods on -} - -// IBridgeCallbackCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IBridgeCallbackCallerRaw struct { - Contract *IBridgeCallbackCaller // Generic read-only contract binding to access the raw methods on -} - -// IBridgeCallbackTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IBridgeCallbackTransactorRaw struct { - Contract *IBridgeCallbackTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewIBridgeCallback creates a new instance of IBridgeCallback, bound to a specific deployed contract. -func NewIBridgeCallback(address common.Address, backend bind.ContractBackend) (*IBridgeCallback, error) { - contract, err := bindIBridgeCallback(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &IBridgeCallback{IBridgeCallbackCaller: IBridgeCallbackCaller{contract: contract}, IBridgeCallbackTransactor: IBridgeCallbackTransactor{contract: contract}, IBridgeCallbackFilterer: IBridgeCallbackFilterer{contract: contract}}, nil -} - -// NewIBridgeCallbackCaller creates a new read-only instance of IBridgeCallback, bound to a specific deployed contract. -func NewIBridgeCallbackCaller(address common.Address, caller bind.ContractCaller) (*IBridgeCallbackCaller, error) { - contract, err := bindIBridgeCallback(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IBridgeCallbackCaller{contract: contract}, nil -} - -// NewIBridgeCallbackTransactor creates a new write-only instance of IBridgeCallback, bound to a specific deployed contract. -func NewIBridgeCallbackTransactor(address common.Address, transactor bind.ContractTransactor) (*IBridgeCallbackTransactor, error) { - contract, err := bindIBridgeCallback(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IBridgeCallbackTransactor{contract: contract}, nil -} - -// NewIBridgeCallbackFilterer creates a new log filterer instance of IBridgeCallback, bound to a specific deployed contract. -func NewIBridgeCallbackFilterer(address common.Address, filterer bind.ContractFilterer) (*IBridgeCallbackFilterer, error) { - contract, err := bindIBridgeCallback(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IBridgeCallbackFilterer{contract: contract}, nil -} - -// bindIBridgeCallback binds a generic wrapper to an already deployed contract. -func bindIBridgeCallback(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IBridgeCallbackMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IBridgeCallback *IBridgeCallbackRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IBridgeCallback.Contract.IBridgeCallbackCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IBridgeCallback *IBridgeCallbackRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IBridgeCallback.Contract.IBridgeCallbackTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IBridgeCallback *IBridgeCallbackRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IBridgeCallback.Contract.IBridgeCallbackTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_IBridgeCallback *IBridgeCallbackCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _IBridgeCallback.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_IBridgeCallback *IBridgeCallbackTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _IBridgeCallback.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_IBridgeCallback *IBridgeCallbackTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _IBridgeCallback.Contract.contract.Transact(opts, method, params...) -} - -// BridgeCallback is a paid mutator transaction binding the contract method 0x13997566. -// -// Solidity: function bridgeCallback(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() -func (_IBridgeCallback *IBridgeCallbackTransactor) BridgeCallback(opts *bind.TransactOpts, _sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { - return _IBridgeCallback.contract.Transact(opts, "bridgeCallback", _sender, _refund, _tokens, _amounts, _data, _memo) -} - -// BridgeCallback is a paid mutator transaction binding the contract method 0x13997566. -// -// Solidity: function bridgeCallback(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() -func (_IBridgeCallback *IBridgeCallbackSession) BridgeCallback(_sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { - return _IBridgeCallback.Contract.BridgeCallback(&_IBridgeCallback.TransactOpts, _sender, _refund, _tokens, _amounts, _data, _memo) -} - -// BridgeCallback is a paid mutator transaction binding the contract method 0x13997566. -// -// Solidity: function bridgeCallback(address _sender, address _refund, address[] _tokens, uint256[] _amounts, bytes _data, bytes _memo) returns() -func (_IBridgeCallback *IBridgeCallbackTransactorSession) BridgeCallback(_sender common.Address, _refund common.Address, _tokens []common.Address, _amounts []*big.Int, _data []byte, _memo []byte) (*types.Transaction, error) { - return _IBridgeCallback.Contract.BridgeCallback(&_IBridgeCallback.TransactOpts, _sender, _refund, _tokens, _amounts, _data, _memo) -} diff --git a/solidity/contracts/bridge/BridgeCallFee.sol b/solidity/contracts/bridge/BridgeCallFee.sol deleted file mode 100644 index 0fc9feed..00000000 --- a/solidity/contracts/bridge/BridgeCallFee.sol +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {IERC20MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; -import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; - -import {IBridgeCallback} from "./IBridgeCallback.sol"; - -/* solhint-disable custom-errors */ - -contract BridgeCallFee is - IBridgeCallback, - Initializable, - ContextUpgradeable, - UUPSUpgradeable, - OwnableUpgradeable -{ - using SafeERC20Upgradeable for IERC20MetadataUpgradeable; - - address public bridge; - mapping(address => mapping(address => uint256)) public fee; - - function updateBridge(address _bridge) public onlyOwner { - bridge = _bridge; - } - - function bridgeCallback( - address _sender, - address _refund, - address[] calldata _tokens, - uint256[] calldata _amounts, - bytes memory _data, - bytes memory _memo - ) external override onlyBridge { - uint256 tokenLen = _tokens.length; - - // deduction of fee - if (tokenLen > 0) { - address feeToken = _tokens[tokenLen - 1]; - uint256 feeAmount = _amounts[tokenLen - 1]; - // solhint-disable-next-line avoid-tx-origin - fee[tx.origin][feeToken] += feeAmount; - emit BridgeCallFeeEvent( - // solhint-disable-next-line avoid-tx-origin - tx.origin, - feeToken, - feeAmount - ); - tokenLen = tokenLen - 1; - } - - (address target, bytes memory targetMemo) = abi.decode( - _memo, - (address, bytes) - ); - for (uint256 i = 0; i < tokenLen; i++) { - IERC20MetadataUpgradeable(_tokens[i]).transfer(target, _amounts[i]); - } - IBridgeCallback(target).bridgeCallback( - _sender, - _refund, - _tokens[0:tokenLen], - _amounts[0:tokenLen], - _data, - targetMemo - ); - } - - function withdraw(address[] memory _tokens) public { - require(_tokens.length > 0, "empty tokens"); - for (uint256 i = 0; i < _tokens.length; i++) { - uint256 feeAmount = fee[_msgSender()][_tokens[i]]; - if (feeAmount == 0) { - continue; - } - fee[_msgSender()][_tokens[i]] = 0; - IERC20MetadataUpgradeable(_tokens[i]).transfer( - _msgSender(), - feeAmount - ); - emit WithdrawFeeEvent(_msgSender(), _tokens[i], feeAmount); - } - } - - modifier onlyBridge() { - require(_msgSender() == bridge, "only bridge can call this function"); - _; - } - - event BridgeCallFeeEvent( - address indexed _receiver, - address indexed _token, - uint256 _amount - ); - - event WithdrawFeeEvent( - address indexed _receiver, - address indexed _token, - uint256 _amount - ); - - // solhint-disable-next-line no-empty-blocks - function _authorizeUpgrade(address) internal override onlyOwner {} - - function initialize(address _bridge) public virtual initializer { - bridge = _bridge; - - __Ownable_init(); - __UUPSUpgradeable_init(); - } -} diff --git a/solidity/contracts/bridge/FxBridgeLogic.sol b/solidity/contracts/bridge/FxBridgeLogic.sol index 5ef53a73..cc41681d 100644 --- a/solidity/contracts/bridge/FxBridgeLogic.sol +++ b/solidity/contracts/bridge/FxBridgeLogic.sol @@ -12,7 +12,7 @@ import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {IERC20ExtensionsUpgradeable} from "./IERC20ExtensionsUpgradeable.sol"; -import {IBridgeCallback} from "./IBridgeCallback.sol"; +import {IBridgeCallContext} from "./IBridgeCallContext.sol"; /* solhint-disable custom-errors */ @@ -586,14 +586,15 @@ contract FxBridgeLogic is _input.tokens, _input.amounts ); + } + if (_input.to.isContract()) { if (_input.eventNonce > 0) { + IBridgeCallContext(_input.to).onRevert(_input.data); return; } - } - if (_input.to.isContract()) { - IBridgeCallback(_input.to).bridgeCallback( + IBridgeCallContext(_input.to).onBridgeCall( _input.sender, _input.refund, _input.tokens, diff --git a/solidity/contracts/bridge/FxBridgeLogicETH.sol b/solidity/contracts/bridge/FxBridgeLogicETH.sol index ac2a59ec..e9d1e7a5 100644 --- a/solidity/contracts/bridge/FxBridgeLogicETH.sol +++ b/solidity/contracts/bridge/FxBridgeLogicETH.sol @@ -12,7 +12,7 @@ import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {IERC20ExtensionsUpgradeable} from "./IERC20ExtensionsUpgradeable.sol"; -import {IBridgeCallback} from "./IBridgeCallback.sol"; +import {IBridgeCallContext} from "./IBridgeCallContext.sol"; /* solhint-disable custom-errors */ @@ -622,14 +622,15 @@ contract FxBridgeLogicETH is _input.tokens, _input.amounts ); + } + if (_input.to.isContract()) { if (_input.eventNonce > 0) { + IBridgeCallContext(_input.to).onRevert(_input.data); return; } - } - if (_input.to.isContract()) { - IBridgeCallback(_input.to).bridgeCallback( + IBridgeCallContext(_input.to).onBridgeCall( _input.sender, _input.refund, _input.tokens, diff --git a/solidity/contracts/bridge/IBridgeCallback.sol b/solidity/contracts/bridge/IBridgeCallContext.sol similarity index 69% rename from solidity/contracts/bridge/IBridgeCallback.sol rename to solidity/contracts/bridge/IBridgeCallContext.sol index 8fc19535..125b82b3 100644 --- a/solidity/contracts/bridge/IBridgeCallback.sol +++ b/solidity/contracts/bridge/IBridgeCallContext.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -interface IBridgeCallback { - function bridgeCallback( +interface IBridgeCallContext { + function onBridgeCall( address _sender, address _refund, address[] memory _tokens, @@ -10,4 +10,6 @@ interface IBridgeCallback { bytes memory _data, bytes memory _memo ) external; + + function onRevert(bytes memory _msg) external; } diff --git a/solidity/contracts/test/BridgeCallbackTest.sol b/solidity/contracts/test/BridgeCallContextTest.sol similarity index 64% rename from solidity/contracts/test/BridgeCallbackTest.sol rename to solidity/contracts/test/BridgeCallContextTest.sol index c6f22644..37cd7753 100644 --- a/solidity/contracts/test/BridgeCallbackTest.sol +++ b/solidity/contracts/test/BridgeCallContextTest.sol @@ -1,20 +1,22 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; -import {IBridgeCallback} from "../bridge/IBridgeCallback.sol"; +import {IBridgeCallContext} from "../bridge/IBridgeCallContext.sol"; /* solhint-disable custom-errors */ -contract BridgeCallbackTest is IBridgeCallback { +contract BridgeCallContextTest is IBridgeCallContext { address public fxBridge; bool public callFlag; + bool public revertFlag; constructor(address _fxBridge) { fxBridge = _fxBridge; callFlag = false; + revertFlag = false; } - function bridgeCallback( + function onBridgeCall( address, address, address[] memory, @@ -25,6 +27,10 @@ contract BridgeCallbackTest is IBridgeCallback { callFlag = !callFlag; } + function onRevert(bytes memory) external override onlyFxBridge { + revertFlag = !revertFlag; + } + modifier onlyFxBridge() { require(msg.sender == fxBridge, "only fx bridge"); _; diff --git a/solidity/test/bridge_fee.ts b/solidity/test/bridge_fee.ts index 80c1d80d..8edadd30 100644 --- a/solidity/test/bridge_fee.ts +++ b/solidity/test/bridge_fee.ts @@ -4,8 +4,7 @@ import { expect } from "chai"; import { ERC20TokenTest, FxBridgeLogic, - BridgeCallFee, - BridgeCallbackTest, + BridgeCallContextTest, } from "../typechain-types"; import { AbiCoder, encodeBytes32String } from "ethers"; import { getSignerAddresses, submitBridgeCall } from "./common"; @@ -16,8 +15,7 @@ describe("submit bridge call tests", function () { let user1: HardhatEthersSigner; let erc20Token: ERC20TokenTest; let fxBridge: FxBridgeLogic; - let bridgeCallFee: BridgeCallFee; - let bridgeCallback: BridgeCallbackTest; + let bridgeCallContextTest: BridgeCallContextTest; let token1: ERC20TokenTest; let token2: ERC20TokenTest; @@ -93,30 +91,11 @@ describe("submit bridge call tests", function () { await erc20Token.transferOwnership(await fxBridge.getAddress()); - const bridgeCallFeeFactory = await ethers.getContractFactory( - "BridgeCallFee" + const bridgeCallContextTestFactory = await ethers.getContractFactory( + "BridgeCallContextTest" ); - const bridgeCallFeeDeploy = await bridgeCallFeeFactory.deploy(); - - const bridgeCallFeeERC1967Proxy = await ethers.getContractFactory( - "ERC1967Proxy" - ); - const bridgeCallFeeProxy = await bridgeCallFeeERC1967Proxy.deploy( - await bridgeCallFeeDeploy.getAddress(), - "0x" - ); - - bridgeCallFee = await ethers.getContractAt( - "BridgeCallFee", - await bridgeCallFeeProxy.getAddress() - ); - await bridgeCallFee.initialize(await fxBridge.getAddress()); - - const bridgeCallbackFactory = await ethers.getContractFactory( - "BridgeCallbackTest" - ); - bridgeCallback = await bridgeCallbackFactory.deploy( - await bridgeCallFee.getAddress() + bridgeCallContextTest = await bridgeCallContextTestFactory.deploy( + await fxBridge.getAddress() ); const erc2TokenFactory = await ethers.getContractFactory("ERC20TokenTest"); @@ -152,7 +131,7 @@ describe("submit bridge call tests", function () { const erc20TokenAddress = await erc20Token.getAddress(); const amount = "1000"; const timeout = (await ethers.provider.getBlockNumber()) + 1000; - const bridgeCallFeeAddress = await bridgeCallFee.getAddress(); + const bridgeCallContextAddress = await bridgeCallContextTest.getAddress(); await erc20Token.transfer( await fxBridge.getAddress(), @@ -163,16 +142,16 @@ describe("submit bridge call tests", function () { const memo = new AbiCoder().encode( ["address", "bytes"], - [await bridgeCallback.getAddress(), "0x"] + [await bridgeCallContextTest.getAddress(), "0x"] ); - const deployBal1 = await token1.balanceOf(bridgeCallFeeAddress); - const callFlag1 = await bridgeCallback.callFlag(); + const deployBal1 = await token1.balanceOf(bridgeCallContextAddress); + const callFlag1 = await bridgeCallContextTest.callFlag(); await submitBridgeCall( gravityId, user1.address, - bridgeCallFeeAddress, - bridgeCallFeeAddress, + bridgeCallContextAddress, + bridgeCallContextAddress, "0x", memo, [erc20TokenAddress, await token1.getAddress()], @@ -185,9 +164,9 @@ describe("submit bridge call tests", function () { fxBridge ); - const deployBal2 = await token1.balanceOf(bridgeCallFeeAddress); + const deployBal2 = await token1.balanceOf(bridgeCallContextAddress); expect(deployBal2).to.be.equal(deployBal1 + BigInt(amount)); - const callFlag2 = await bridgeCallback.callFlag(); + const callFlag2 = await bridgeCallContextTest.callFlag(); expect(callFlag2).to.be.equal(!callFlag1); }); }); diff --git a/solidity/test/submit_bridge_call.ts b/solidity/test/submit_bridge_call.ts index 4fb87790..29bffb1c 100644 --- a/solidity/test/submit_bridge_call.ts +++ b/solidity/test/submit_bridge_call.ts @@ -4,7 +4,7 @@ import { expect } from "chai"; import { ERC20TokenTest, FxBridgeLogic, - BridgeCallbackTest, + BridgeCallContextTest, } from "../typechain-types"; import { encodeBytes32String } from "ethers"; import { getSignerAddresses, submitBridgeCall } from "./common"; @@ -15,7 +15,7 @@ describe("submit bridge call tests", function () { let user1: HardhatEthersSigner; let erc20Token: ERC20TokenTest; let fxBridge: FxBridgeLogic; - let bridgeCallback: BridgeCallbackTest; + let bridgeCallContextTest: BridgeCallContextTest; let totalSupply = "10000"; const gravityId: string = encodeBytes32String("eth-fxcore"); @@ -88,10 +88,10 @@ describe("submit bridge call tests", function () { await erc20Token.transferOwnership(await fxBridge.getAddress()); - const bridgeCallbackFactory = await ethers.getContractFactory( - "BridgeCallbackTest" + const bridgeCallContextTestFactory = await ethers.getContractFactory( + "BridgeCallContextTest" ); - bridgeCallback = await bridgeCallbackFactory.deploy( + bridgeCallContextTest = await bridgeCallContextTestFactory.deploy( await fxBridge.getAddress() ); }); @@ -119,23 +119,23 @@ describe("submit bridge call tests", function () { ); }); - it("submit bridge call with bridge callback", async function () { + it("submit bridge call with bridge context on bridge call", async function () { const erc20TokenAddress = await erc20Token.getAddress(); const amount = "1000"; const timeout = (await ethers.provider.getBlockNumber()) + 1000; - const bridgeCallbackAddress = await bridgeCallback.getAddress(); + const bridgeCallContextAddress = await bridgeCallContextTest.getAddress(); await erc20Token.transfer( await fxBridge.getAddress(), ethers.parseEther("1") ); - const ownerBal1 = await erc20Token.balanceOf(bridgeCallbackAddress); + const ownerBal1 = await erc20Token.balanceOf(bridgeCallContextAddress); await submitBridgeCall( gravityId, user1.address, user1.address, - bridgeCallbackAddress, + bridgeCallContextAddress, "0x", "0x", [erc20TokenAddress], @@ -147,8 +147,44 @@ describe("submit bridge call tests", function () { powers, fxBridge ); - const ownerBal2 = await erc20Token.balanceOf(bridgeCallbackAddress); + const ownerBal2 = await erc20Token.balanceOf(bridgeCallContextAddress); expect(ownerBal2).to.equal(ownerBal1 + BigInt(amount)); + expect(await bridgeCallContextTest.callFlag()).to.equal(true); + expect(await bridgeCallContextTest.revertFlag()).to.equal(false); + }); + + it("submit bridge call with bridge context on revert", async function () { + const erc20TokenAddress = await erc20Token.getAddress(); + const amount = "1000"; + const timeout = (await ethers.provider.getBlockNumber()) + 1000; + const bridgeCallContextAddress = await bridgeCallContextTest.getAddress(); + + await erc20Token.transfer( + await fxBridge.getAddress(), + ethers.parseEther("1") + ); + + const ownerBal1 = await erc20Token.balanceOf(user1.address); + await submitBridgeCall( + gravityId, + user1.address, + user1.address, + bridgeCallContextAddress, + "0x", + "0x", + [erc20TokenAddress], + [amount], + 1, + timeout, + 1, + validators, + powers, + fxBridge + ); + const ownerBal2 = await erc20Token.balanceOf(user1.address); + expect(ownerBal2).to.equal(ownerBal1 + BigInt(amount)); + expect(await bridgeCallContextTest.revertFlag()).to.equal(true); + expect(await bridgeCallContextTest.callFlag()).to.equal(false); }); it("submit bridge call with refund", async function () { diff --git a/x/crosschain/keeper/bridge_call_in.go b/x/crosschain/keeper/bridge_call_in.go index adc21dab..c2efeb6f 100644 --- a/x/crosschain/keeper/bridge_call_in.go +++ b/x/crosschain/keeper/bridge_call_in.go @@ -108,7 +108,7 @@ func (k Keeper) BridgeCallEvm(ctx sdk.Context, sender, refundAddr, to, receiverA callEvmSender = sender } else { var err error - args, err = contract.PackBridgeCallback(sender, refundAddr, tokens, amounts, data, memo) + args, err = contract.PackOnBridgeCall(sender, refundAddr, tokens, amounts, data, memo) if err != nil { return err }