From f3532fc695bef32dea1b47bf6b8a9e353c2dee37 Mon Sep 17 00:00:00 2001 From: huy Date: Mon, 3 Jun 2024 11:54:47 -0700 Subject: [PATCH 1/3] Splits v2 contract --- common/contracts/split-main-1_0.go | 77 ---------------------------- common/contracts/split-main-1_1.go | 77 ---------------------------- common/contracts/split-warehouse.go | 79 +++++++++++++++++++++++++++++ server/wallet/claim-rewards.go | 37 ++++++++++---- shared/api/wallet.go | 1 + shared/config/resources.go | 19 ++----- 6 files changed, 113 insertions(+), 177 deletions(-) delete mode 100644 common/contracts/split-main-1_0.go delete mode 100644 common/contracts/split-main-1_1.go create mode 100644 common/contracts/split-warehouse.go diff --git a/common/contracts/split-main-1_0.go b/common/contracts/split-main-1_0.go deleted file mode 100644 index 359faaa..0000000 --- a/common/contracts/split-main-1_0.go +++ /dev/null @@ -1,77 +0,0 @@ -package swcontracts - -import ( - "fmt" - "math/big" - "strings" - "sync" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - batch "github.com/rocket-pool/batch-query" - "github.com/rocket-pool/node-manager-core/eth" -) - -const ( - splitMainAbiString_1_0 string = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Create2Error","type":"error"},{"inputs":[],"name":"CreateError","type":"error"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"InvalidNewController","type":"error"},{"inputs":[{"internalType":"uint256","name":"accountsLength","type":"uint256"},{"internalType":"uint256","name":"allocationsLength","type":"uint256"}],"name":"InvalidSplit__AccountsAndAllocationsMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidSplit__AccountsOutOfOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidSplit__AllocationMustBePositive","type":"error"},{"inputs":[{"internalType":"uint32","name":"allocationsSum","type":"uint32"}],"name":"InvalidSplit__InvalidAllocationsSum","type":"error"},{"inputs":[{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"InvalidSplit__InvalidDistributorFee","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"InvalidSplit__InvalidHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"accountsLength","type":"uint256"}],"name":"InvalidSplit__TooFewAccounts","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"}],"name":"CancelControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"address","name":"previousController","type":"address"},{"indexed":true,"internalType":"address","name":"newController","type":"address"}],"name":"ControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"}],"name":"CreateSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"distributorAddress","type":"address"}],"name":"DistributeERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"distributorAddress","type":"address"}],"name":"DistributeETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"address","name":"newPotentialController","type":"address"}],"name":"InitiateControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"}],"name":"UpdateSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"contract ERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"PERCENTAGE_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"acceptControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"cancelControlTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"controller","type":"address"}],"name":"createSplit","outputs":[{"internalType":"address","name":"split","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"distributeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"distributeETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"}],"name":"getERC20Balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getETHBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getNewPotentialController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"makeSplitImmutable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"predictImmutableSplitAddress","outputs":[{"internalType":"address","name":"split","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address","name":"newController","type":"address"}],"name":"transferControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"updateAndDistributeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"updateAndDistributeETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"updateSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"withdrawETH","type":"uint256"},{"internalType":"contract ERC20[]","name":"tokens","type":"address[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]` -) - -// ABI cache -var splitMainAbi_1_0 abi.ABI -var splitMainOnce_1_0 sync.Once - -// Binding for the SplitMain "v1.0" contract -// See https://github.com/0xSplits/splits-contracts/blob/main/contracts/interfaces/ISplitMain.sol -type SplitMain1_0 struct { - contract *eth.Contract - txMgr *eth.TransactionManager -} - -// Create a new SplitMain instance -func NewSplitMain1_0(address common.Address, ec eth.IExecutionClient, txMgr *eth.TransactionManager) (*SplitMain1_0, error) { - // Parse the ABI - var err error - splitMainOnce_1_0.Do(func() { - var parsedAbi abi.ABI - parsedAbi, err = abi.JSON(strings.NewReader(splitMainAbiString_1_0)) - if err == nil { - splitMainAbi_1_0 = parsedAbi - } - }) - if err != nil { - return nil, fmt.Errorf("error parsing Stakewise Vault ABI: %w", err) - } - - // Create the contract - contract := ð.Contract{ - ContractImpl: bind.NewBoundContract(address, splitMainAbi_1_0, ec, ec, ec), - Address: address, - ABI: &splitMainAbi_1_0, - } - - return &SplitMain1_0{ - contract: contract, - txMgr: txMgr, - }, nil -} - -// ============= -// === Calls === -// ============= - -func (c *SplitMain1_0) GetEthBalance(mc *batch.MultiCaller, out **big.Int, account common.Address) { - eth.AddCallToMulticaller(mc, c.contract, out, "getETHBalance", account) -} - -func (c *SplitMain1_0) GetErc20Balance(mc *batch.MultiCaller, out **big.Int, account common.Address, token common.Address) { - eth.AddCallToMulticaller(mc, c.contract, out, "getERC20Balance", account, token) -} - -// ==================== -// === Transactions === -// ==================== - -func (c *SplitMain1_0) Withdraw(address common.Address, ethAmountWithdraw *big.Int, claimTokenList []common.Address, opts *bind.TransactOpts) (*eth.TransactionInfo, error) { - return c.txMgr.CreateTransactionInfo(c.contract, "withdraw", opts, address, ethAmountWithdraw, claimTokenList) -} diff --git a/common/contracts/split-main-1_1.go b/common/contracts/split-main-1_1.go deleted file mode 100644 index 6b820f5..0000000 --- a/common/contracts/split-main-1_1.go +++ /dev/null @@ -1,77 +0,0 @@ -package swcontracts - -import ( - "fmt" - "math/big" - "strings" - "sync" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - batch "github.com/rocket-pool/batch-query" - "github.com/rocket-pool/node-manager-core/eth" -) - -const ( - splitMainAbiString_1_1 string = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Create2Error","type":"error"},{"inputs":[],"name":"CreateError","type":"error"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"InvalidNewController","type":"error"},{"inputs":[{"internalType":"uint256","name":"accountsLength","type":"uint256"},{"internalType":"uint256","name":"allocationsLength","type":"uint256"}],"name":"InvalidSplit__AccountsAndAllocationsMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidSplit__AccountsOutOfOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"InvalidSplit__AllocationMustBePositive","type":"error"},{"inputs":[{"internalType":"uint32","name":"allocationsSum","type":"uint32"}],"name":"InvalidSplit__InvalidAllocationsSum","type":"error"},{"inputs":[{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"InvalidSplit__InvalidDistributorFee","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"InvalidSplit__InvalidHash","type":"error"},{"inputs":[{"internalType":"uint256","name":"accountsLength","type":"uint256"}],"name":"InvalidSplit__TooFewAccounts","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"}],"name":"CancelControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"address","name":"previousController","type":"address"},{"indexed":true,"internalType":"address","name":"newController","type":"address"}],"name":"ControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":false,"internalType":"address[]","name":"accounts","type":"address[]"},{"indexed":false,"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"indexed":false,"internalType":"uint32","name":"distributorFee","type":"uint32"},{"indexed":false,"internalType":"address","name":"controller","type":"address"}],"name":"CreateSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"contract ERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"distributorAddress","type":"address"}],"name":"DistributeERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"distributorAddress","type":"address"}],"name":"DistributeETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":true,"internalType":"address","name":"newPotentialController","type":"address"}],"name":"InitiateControlTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"split","type":"address"},{"indexed":false,"internalType":"address[]","name":"accounts","type":"address[]"},{"indexed":false,"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"indexed":false,"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"UpdateSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"contract ERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"PERCENTAGE_SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"acceptControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"cancelControlTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"controller","type":"address"}],"name":"createSplit","outputs":[{"internalType":"address","name":"split","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"distributeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"distributeETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"}],"name":"getERC20Balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getETHBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"getNewPotentialController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"}],"name":"makeSplitImmutable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"predictImmutableSplitAddress","outputs":[{"internalType":"address","name":"split","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address","name":"newController","type":"address"}],"name":"transferControl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"contract ERC20","name":"token","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"updateAndDistributeERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"},{"internalType":"address","name":"distributorAddress","type":"address"}],"name":"updateAndDistributeETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"split","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint32[]","name":"percentAllocations","type":"uint32[]"},{"internalType":"uint32","name":"distributorFee","type":"uint32"}],"name":"updateSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"withdrawETH","type":"uint256"},{"internalType":"contract ERC20[]","name":"tokens","type":"address[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]` -) - -// ABI cache -var splitMainAbi_1_1 abi.ABI -var splitMainOnce_1_1 sync.Once - -// Binding for the SplitMain "v1.1" contract -// See https://github.com/0xSplits/splits-contracts/blob/holesky-2/contracts/interfaces/ISplitMain.sol -type SplitMain1_1 struct { - contract *eth.Contract - txMgr *eth.TransactionManager -} - -// Create a new SplitMain instance -func NewSplitMain1_1(address common.Address, ec eth.IExecutionClient, txMgr *eth.TransactionManager) (*SplitMain1_1, error) { - // Parse the ABI - var err error - splitMainOnce_1_1.Do(func() { - var parsedAbi abi.ABI - parsedAbi, err = abi.JSON(strings.NewReader(splitMainAbiString_1_1)) - if err == nil { - splitMainAbi_1_1 = parsedAbi - } - }) - if err != nil { - return nil, fmt.Errorf("error parsing Stakewise Vault ABI: %w", err) - } - - // Create the contract - contract := ð.Contract{ - ContractImpl: bind.NewBoundContract(address, splitMainAbi_1_1, ec, ec, ec), - Address: address, - ABI: &splitMainAbi_1_1, - } - - return &SplitMain1_1{ - contract: contract, - txMgr: txMgr, - }, nil -} - -// ============= -// === Calls === -// ============= - -func (c *SplitMain1_1) GetEthBalance(mc *batch.MultiCaller, out **big.Int, account common.Address) { - eth.AddCallToMulticaller(mc, c.contract, out, "getETHBalance", account) -} - -func (c *SplitMain1_1) GetErc20Balance(mc *batch.MultiCaller, out **big.Int, account common.Address, token common.Address) { - eth.AddCallToMulticaller(mc, c.contract, out, "getERC20Balance", account, token) -} - -// ==================== -// === Transactions === -// ==================== - -func (c *SplitMain1_1) Withdraw(address common.Address, ethAmountWithdraw *big.Int, claimTokenList []common.Address, opts *bind.TransactOpts) (*eth.TransactionInfo, error) { - return c.txMgr.CreateTransactionInfo(c.contract, "withdraw", opts, address, ethAmountWithdraw, claimTokenList) -} diff --git a/common/contracts/split-warehouse.go b/common/contracts/split-warehouse.go new file mode 100644 index 0000000..c3d0da9 --- /dev/null +++ b/common/contracts/split-warehouse.go @@ -0,0 +1,79 @@ +package swcontracts + +import ( + "fmt" + "math/big" + "strings" + "sync" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + batch "github.com/rocket-pool/batch-query" + "github.com/rocket-pool/node-manager-core/eth" +) + +const ( + splitWarehouseAbiString string = `[{"type":"constructor","inputs":[{"name":"_native_token_name","type":"string","internalType":"string"},{"name":"_native_token_symbol","type":"string","internalType":"string"}],"stateMutability":"nonpayable"},{"type":"function","name":"APPROVE_AND_CALL_TYPE_HASH","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DOMAIN_SEPARATOR","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"NATIVE_TOKEN","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"NATIVE_TOKEN_ID","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"PERCENTAGE_SCALE","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"allowance","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"spender","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"amount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"approve","inputs":[{"name":"_spender","type":"address","internalType":"address"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"approveBySig","inputs":[{"name":"_owner","type":"address","internalType":"address"},{"name":"_spender","type":"address","internalType":"address"},{"name":"_operator","type":"bool","internalType":"bool"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"},{"name":"_nonce","type":"uint256","internalType":"uint256"},{"name":"_deadline","type":"uint48","internalType":"uint48"},{"name":"_signature","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"balanceOf","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"amount","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"batchDeposit","inputs":[{"name":"_receivers","type":"address[]","internalType":"address[]"},{"name":"_token","type":"address","internalType":"address"},{"name":"_amounts","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"batchTransfer","inputs":[{"name":"_receivers","type":"address[]","internalType":"address[]"},{"name":"_token","type":"address","internalType":"address"},{"name":"_amounts","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"decimals","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"deposit","inputs":[{"name":"_receiver","type":"address","internalType":"address"},{"name":"_token","type":"address","internalType":"address"},{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"eip712Domain","inputs":[],"outputs":[{"name":"fields","type":"bytes1","internalType":"bytes1"},{"name":"name","type":"string","internalType":"string"},{"name":"version","type":"string","internalType":"string"},{"name":"chainId","type":"uint256","internalType":"uint256"},{"name":"verifyingContract","type":"address","internalType":"address"},{"name":"salt","type":"bytes32","internalType":"bytes32"},{"name":"extensions","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"invalidateNonce","inputs":[{"name":"_nonce","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isOperator","inputs":[{"name":"owner","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"approved","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isValidNonce","inputs":[{"name":"_from","type":"address","internalType":"address"},{"name":"_nonce","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"name","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"nonceBitMap","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"word","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"bitMap","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setOperator","inputs":[{"name":"_operator","type":"address","internalType":"address"},{"name":"_approved","type":"bool","internalType":"bool"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"setWithdrawConfig","inputs":[{"name":"_config","type":"tuple","internalType":"struct SplitsWarehouse.WithdrawConfig","components":[{"name":"incentive","type":"uint16","internalType":"uint16"},{"name":"paused","type":"bool","internalType":"bool"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"_interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"supported","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"symbol","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"temporaryApproveAndCall","inputs":[{"name":"_spender","type":"address","internalType":"address"},{"name":"_operator","type":"bool","internalType":"bool"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"},{"name":"_target","type":"address","internalType":"address"},{"name":"_data","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"temporaryApproveAndCallBySig","inputs":[{"name":"_owner","type":"address","internalType":"address"},{"name":"_spender","type":"address","internalType":"address"},{"name":"_operator","type":"bool","internalType":"bool"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"},{"name":"_target","type":"address","internalType":"address"},{"name":"_data","type":"bytes","internalType":"bytes"},{"name":"_nonce","type":"uint256","internalType":"uint256"},{"name":"_deadline","type":"uint48","internalType":"uint48"},{"name":"_signature","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transfer","inputs":[{"name":"_receiver","type":"address","internalType":"address"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"transferFrom","inputs":[{"name":"_sender","type":"address","internalType":"address"},{"name":"_receiver","type":"address","internalType":"address"},{"name":"_id","type":"uint256","internalType":"uint256"},{"name":"_amount","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"nonpayable"},{"type":"function","name":"withdraw","inputs":[{"name":"_owner","type":"address","internalType":"address"},{"name":"_tokens","type":"address[]","internalType":"address[]"},{"name":"_amounts","type":"uint256[]","internalType":"uint256[]"},{"name":"_withdrawer","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"withdraw","inputs":[{"name":"_owner","type":"address","internalType":"address"},{"name":"_token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"withdrawConfig","inputs":[{"name":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"incentive","type":"uint16","internalType":"uint16"},{"name":"paused","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"id","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"EIP712DomainChanged","inputs":[],"anonymous":false},{"type":"event","name":"NonceInvalidation","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"nonce","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSet","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"spender","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"caller","type":"address","indexed":false,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"},{"name":"receiver","type":"address","indexed":true,"internalType":"address"},{"name":"id","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Withdraw","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"withdrawer","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"reward","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawConfigUpdated","inputs":[{"name":"owner","type":"address","indexed":true,"internalType":"address"},{"name":"config","type":"tuple","indexed":false,"internalType":"struct SplitsWarehouse.WithdrawConfig","components":[{"name":"incentive","type":"uint16","internalType":"uint16"},{"name":"paused","type":"bool","internalType":"bool"}]}],"anonymous":false},{"type":"error","name":"ExpiredSignature","inputs":[{"name":"deadline","type":"uint48","internalType":"uint48"}]},{"type":"error","name":"InvalidAck","inputs":[]},{"type":"error","name":"InvalidAmount","inputs":[]},{"type":"error","name":"InvalidNonce","inputs":[]},{"type":"error","name":"InvalidPermitParams","inputs":[]},{"type":"error","name":"InvalidShortString","inputs":[]},{"type":"error","name":"InvalidSigner","inputs":[]},{"type":"error","name":"LengthMismatch","inputs":[]},{"type":"error","name":"Overflow","inputs":[]},{"type":"error","name":"StringTooLong","inputs":[{"name":"str","type":"string","internalType":"string"}]},{"type":"error","name":"WithdrawalPaused","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"ZeroOwner","inputs":[]}]` +) + +// ABI cache +var splitWarehouseAbi abi.ABI +var splitWarehouseOnce sync.Once + +type SplitWarehouse struct { + contract *eth.Contract + txMgr *eth.TransactionManager +} + +// Create a new SplitWarehouse instance +func NewSplitWarehouse(address common.Address, ec eth.IExecutionClient, txMgr *eth.TransactionManager) (*SplitWarehouse, error) { + // Parse the ABI + var err error + splitWarehouseOnce.Do(func() { + var parsedAbi abi.ABI + parsedAbi, err = abi.JSON(strings.NewReader(splitWarehouseAbiString)) + if err == nil { + splitWarehouseAbi = parsedAbi + } + }) + if err != nil { + return nil, fmt.Errorf("error parsing SplitWarehouse ABI: %w", err) + } + + // Create the contract + contract := ð.Contract{ + ContractImpl: bind.NewBoundContract(address, splitWarehouseAbi, ec, ec, ec), + Address: address, + ABI: &splitWarehouseAbi, + } + + return &SplitWarehouse{ + contract: contract, + txMgr: txMgr, + }, nil +} + +// ============= +// === Calls === +// ============= + +func (c *SplitWarehouse) BalanceOf(mc *batch.MultiCaller, out **big.Int, account common.Address, token common.Address) { + eth.AddCallToMulticaller(mc, c.contract, out, "balanceOf", account, ToUint256(token)) +} + +func (c *SplitWarehouse) NativeToken(mc *batch.MultiCaller, out *common.Address) { + eth.AddCallToMulticaller(mc, c.contract, out, "NATIVE_TOKEN") +} + +// ==================== +// === Transactions === +// ==================== + +func (c *SplitWarehouse) Withdraw(address common.Address, amountWithdraw []*big.Int, claimTokenList []common.Address, opts *bind.TransactOpts) (*eth.TransactionInfo, error) { + return c.txMgr.CreateTransactionInfo(c.contract, "withdraw", opts, address, claimTokenList, amountWithdraw, address) +} + +func ToUint256(address common.Address) *big.Int { + return new(big.Int).SetBytes(address.Bytes()) +} diff --git a/server/wallet/claim-rewards.go b/server/wallet/claim-rewards.go index 25aac1a..653ec68 100644 --- a/server/wallet/claim-rewards.go +++ b/server/wallet/claim-rewards.go @@ -65,8 +65,8 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa return types.ResponseStatus_AddressNotPresent, err } - if res.SplitMain == nil { - return types.ResponseStatus_InvalidChainState, fmt.Errorf("no SplitMain contract has been set yet") + if res.SplitWarehouse == nil { + return types.ResponseStatus_InvalidChainState, fmt.Errorf("no SplitWarehouse contract has been set yet") } if res.Vault == nil { return types.ResponseStatus_InvalidChainState, fmt.Errorf("no Stakewise Vault address has been set yet") @@ -74,9 +74,9 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa // Create bindings logger.Debug("Preparing data for claim reward") - splitMainContract, err := swcontracts.NewSplitMain1_1(*res.SplitMain, ec, txMgr) // NOTE: need to parse the actual contract version once event support is added + splitWarehouseContract, err := swcontracts.NewSplitWarehouse(*res.SplitWarehouse, ec, txMgr) // NOTE: need to parse the actual contract version once event support is added if err != nil { - return types.ResponseStatus_Error, fmt.Errorf("error creating SplitMain binding: %w", err) + return types.ResponseStatus_Error, fmt.Errorf("error creating SplitWarehouse binding: %w", err) } token, err := contracts.NewErc20Contract(*res.Vault, ec, qMgr, txMgr, nil) if err != nil { @@ -85,22 +85,41 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa data.TokenName = token.Name() data.TokenSymbol = token.Symbol() + // Get the native token address + err = qMgr.Query(func(mc *batch.MultiCaller) error { + splitWarehouseContract.NativeToken(mc, &data.NativeToken) + return nil + }, nil) + if err != nil { + return types.ResponseStatus_Error, fmt.Errorf("error querying claimable rewards: %w", err) + } + // Get the claimable rewards err = qMgr.Query(func(mc *batch.MultiCaller) error { - splitMainContract.GetErc20Balance(mc, &data.WithdrawableToken, nodeAddress, *res.Vault) - splitMainContract.GetEthBalance(mc, &data.WithdrawableEth, nodeAddress) + splitWarehouseContract.BalanceOf(mc, &data.WithdrawableToken, nodeAddress, *res.Vault) + splitWarehouseContract.BalanceOf(mc, &data.WithdrawableEth, nodeAddress, data.NativeToken) return nil }, nil) if err != nil { return types.ResponseStatus_Error, fmt.Errorf("error querying claimable rewards: %w", err) } - ethFlag := big.NewInt(0) + tokensToWithdraw := []common.Address{} + amountsToWithdraw := []*big.Int{} + if data.WithdrawableEth.Cmp(common.Big0) > 0 { // Only withdraw ETH if there is a balance - ethFlag.Add(ethFlag, common.Big1) + tokensToWithdraw = append(tokensToWithdraw, data.NativeToken) + amountsToWithdraw = append(amountsToWithdraw, data.WithdrawableEth) } - data.TxInfo, err = splitMainContract.Withdraw(nodeAddress, ethFlag, []common.Address{*res.Vault}, opts) + + if data.WithdrawableToken.Cmp(common.Big0) > 0 { + // Only withdraw tokens if there is a balance + tokensToWithdraw = append(tokensToWithdraw, *res.Vault) + amountsToWithdraw = append(amountsToWithdraw, data.WithdrawableToken) + } + + data.TxInfo, err = splitWarehouseContract.Withdraw(nodeAddress, amountsToWithdraw, tokensToWithdraw, opts) if err != nil { return types.ResponseStatus_Error, fmt.Errorf("error creating Withdraw TX: %w", err) } diff --git a/shared/api/wallet.go b/shared/api/wallet.go index 6e908c1..c435f43 100644 --- a/shared/api/wallet.go +++ b/shared/api/wallet.go @@ -17,6 +17,7 @@ type WalletGenerateKeysData struct { } type WalletClaimRewardsData struct { + NativeToken common.Address `json:"nativeToken"` TokenName string `json:"tokenName"` TokenSymbol string `json:"tokenSymbol"` DistributableToken *big.Int `json:"distributableToken"` diff --git a/shared/config/resources.go b/shared/config/resources.go index db6d811..1a27d62 100644 --- a/shared/config/resources.go +++ b/shared/config/resources.go @@ -24,15 +24,9 @@ type StakewiseResources struct { // See https://github.com/stakewise/v3-core/blob/main/contracts/vaults/ethereum/mev/SharedMevEscrow.sol FeeRecipient *common.Address - // The splitter proxy used by the NodeSet vault, which distributes rewards to each node op. - // All Beacon + EL rewards from the Vault and FeeRecipient will end up here at some point, but they will be in the ERC-20 represented by the Vault. - // Funds here can be sent to SplitMain by calling `Distribute` on SplitMain and passing this address in as part of it. - // TODO: Find the "share" per node op address - SplitWallet *common.Address - - // The address of the SplitMain contract, see https://docs.splits.org/core/split for details. + // The address of the SplitWarehouse contract used to hold user funds. // All node op rewards will live here; to claim them, call `Withdraw`. - SplitMain *common.Address + SplitWarehouse *common.Address } // Creates a new resource collection for the given network @@ -43,8 +37,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { NodesetApiUrl: "", Vault: nil, FeeRecipient: nil, - SplitWallet: nil, - SplitMain: nil, + SplitWarehouse: nil, } // Holesky @@ -53,8 +46,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { NodesetApiUrl: "https://staging.nodeset.io/api", Vault: config.HexToAddressPtr("0x646F5285D195e08E309cF9A5aDFDF68D6Fcc51C4"), FeeRecipient: config.HexToAddressPtr("0xc98F25BcAA6B812a07460f18da77AF8385be7b56"), - SplitWallet: config.HexToAddressPtr("0x6fa066F4A6439B8a1537F2D300809f23bFF7d37D"), - SplitMain: config.HexToAddressPtr("0xfC8a305728051367797DADE6Aa0344E0987f5286"), + SplitWarehouse: config.HexToAddressPtr("0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8"), } // Holesky Dev @@ -63,8 +55,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { NodesetApiUrl: "https://staging.nodeset.io/api", Vault: config.HexToAddressPtr("0xf8763855473ce978232bBa37ef90fcFc8aAE10d1"), FeeRecipient: config.HexToAddressPtr("0xc98F25BcAA6B812a07460f18da77AF8385be7b56"), - SplitWallet: nil, - SplitMain: config.HexToAddressPtr("0xfC8a305728051367797DADE6Aa0344E0987f5286"), + SplitWarehouse: config.HexToAddressPtr("0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8"), } holeskyDevResources.Network = hdconfig.Network_HoleskyDev From 080b8cf269cc0f5be139d4fe6b5b4aff9ee11808 Mon Sep 17 00:00:00 2001 From: huy Date: Wed, 5 Jun 2024 08:21:21 -0700 Subject: [PATCH 2/3] joes comments --- common/contracts/split-warehouse.go | 2 +- server/wallet/claim-rewards.go | 8 ++++---- shared/api/wallet.go | 16 ++++++++-------- shared/config/resources.go | 1 + 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/common/contracts/split-warehouse.go b/common/contracts/split-warehouse.go index c3d0da9..7abc4ff 100644 --- a/common/contracts/split-warehouse.go +++ b/common/contracts/split-warehouse.go @@ -70,7 +70,7 @@ func (c *SplitWarehouse) NativeToken(mc *batch.MultiCaller, out *common.Address) // === Transactions === // ==================== -func (c *SplitWarehouse) Withdraw(address common.Address, amountWithdraw []*big.Int, claimTokenList []common.Address, opts *bind.TransactOpts) (*eth.TransactionInfo, error) { +func (c *SplitWarehouse) Withdraw(address common.Address, claimTokenList []common.Address, amountWithdraw []*big.Int, opts *bind.TransactOpts) (*eth.TransactionInfo, error) { return c.txMgr.CreateTransactionInfo(c.contract, "withdraw", opts, address, claimTokenList, amountWithdraw, address) } diff --git a/server/wallet/claim-rewards.go b/server/wallet/claim-rewards.go index 653ec68..2f6aaf9 100644 --- a/server/wallet/claim-rewards.go +++ b/server/wallet/claim-rewards.go @@ -97,7 +97,7 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa // Get the claimable rewards err = qMgr.Query(func(mc *batch.MultiCaller) error { splitWarehouseContract.BalanceOf(mc, &data.WithdrawableToken, nodeAddress, *res.Vault) - splitWarehouseContract.BalanceOf(mc, &data.WithdrawableEth, nodeAddress, data.NativeToken) + splitWarehouseContract.BalanceOf(mc, &data.WithdrawableNativeToken, nodeAddress, data.NativeToken) return nil }, nil) if err != nil { @@ -107,10 +107,10 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa tokensToWithdraw := []common.Address{} amountsToWithdraw := []*big.Int{} - if data.WithdrawableEth.Cmp(common.Big0) > 0 { + if data.WithdrawableNativeToken.Cmp(common.Big0) > 0 { // Only withdraw ETH if there is a balance tokensToWithdraw = append(tokensToWithdraw, data.NativeToken) - amountsToWithdraw = append(amountsToWithdraw, data.WithdrawableEth) + amountsToWithdraw = append(amountsToWithdraw, data.WithdrawableNativeToken) } if data.WithdrawableToken.Cmp(common.Big0) > 0 { @@ -119,7 +119,7 @@ func (c *walletClaimRewardsContext) PrepareData(data *swapi.WalletClaimRewardsDa amountsToWithdraw = append(amountsToWithdraw, data.WithdrawableToken) } - data.TxInfo, err = splitWarehouseContract.Withdraw(nodeAddress, amountsToWithdraw, tokensToWithdraw, opts) + data.TxInfo, err = splitWarehouseContract.Withdraw(nodeAddress, tokensToWithdraw, amountsToWithdraw, opts) if err != nil { return types.ResponseStatus_Error, fmt.Errorf("error creating Withdraw TX: %w", err) } diff --git a/shared/api/wallet.go b/shared/api/wallet.go index c435f43..84154d4 100644 --- a/shared/api/wallet.go +++ b/shared/api/wallet.go @@ -17,12 +17,12 @@ type WalletGenerateKeysData struct { } type WalletClaimRewardsData struct { - NativeToken common.Address `json:"nativeToken"` - TokenName string `json:"tokenName"` - TokenSymbol string `json:"tokenSymbol"` - DistributableToken *big.Int `json:"distributableToken"` - DistributableEth *big.Int `json:"distributableEth"` - WithdrawableToken *big.Int `json:"withdrawableToken"` - WithdrawableEth *big.Int `json:"withdrawableEth"` - TxInfo *eth.TransactionInfo `json:"txInfo"` + NativeToken common.Address `json:"nativeToken"` + TokenName string `json:"tokenName"` + TokenSymbol string `json:"tokenSymbol"` + DistributableToken *big.Int `json:"distributableToken"` + DistributableEth *big.Int `json:"distributableEth"` + WithdrawableToken *big.Int `json:"withdrawableToken"` + WithdrawableNativeToken *big.Int `json:"withdrawableNativeToken"` + TxInfo *eth.TransactionInfo `json:"txInfo"` } diff --git a/shared/config/resources.go b/shared/config/resources.go index 1a27d62..78be11e 100644 --- a/shared/config/resources.go +++ b/shared/config/resources.go @@ -26,6 +26,7 @@ type StakewiseResources struct { // The address of the SplitWarehouse contract used to hold user funds. // All node op rewards will live here; to claim them, call `Withdraw`. + // See https://docs.splits.org/core/warehouse SplitWarehouse *common.Address } From 7c419b19de7676c365244c3cf4856c08df53bdff Mon Sep 17 00:00:00 2001 From: huy Date: Tue, 11 Jun 2024 09:04:45 -0700 Subject: [PATCH 3/3] Add PullSplit to resources --- shared/config/resources.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shared/config/resources.go b/shared/config/resources.go index 78be11e..c6487d1 100644 --- a/shared/config/resources.go +++ b/shared/config/resources.go @@ -28,6 +28,10 @@ type StakewiseResources struct { // All node op rewards will live here; to claim them, call `Withdraw`. // See https://docs.splits.org/core/warehouse SplitWarehouse *common.Address + + // The address of the PullSplit contract used to manage recipients/allocations and distributions + // See https://docs.splits.org/core/split-v2 + PullSplit *common.Address } // Creates a new resource collection for the given network @@ -39,6 +43,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { Vault: nil, FeeRecipient: nil, SplitWarehouse: nil, + PullSplit: nil, } // Holesky @@ -48,6 +53,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { Vault: config.HexToAddressPtr("0x646F5285D195e08E309cF9A5aDFDF68D6Fcc51C4"), FeeRecipient: config.HexToAddressPtr("0xc98F25BcAA6B812a07460f18da77AF8385be7b56"), SplitWarehouse: config.HexToAddressPtr("0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8"), + PullSplit: config.HexToAddressPtr("0xAefad0Baa37e1BAF14404bcc2c5E91e4B41c929B"), } // Holesky Dev @@ -57,6 +63,7 @@ func newStakewiseResources(network config.Network) *StakewiseResources { Vault: config.HexToAddressPtr("0xf8763855473ce978232bBa37ef90fcFc8aAE10d1"), FeeRecipient: config.HexToAddressPtr("0xc98F25BcAA6B812a07460f18da77AF8385be7b56"), SplitWarehouse: config.HexToAddressPtr("0x8fb66F38cF86A3d5e8768f8F1754A24A6c661Fb8"), + PullSplit: config.HexToAddressPtr("0xAefad0Baa37e1BAF14404bcc2c5E91e4B41c929B"), } holeskyDevResources.Network = hdconfig.Network_HoleskyDev