diff options
author | Wei-Ning Huang <w@dexon.org> | 2019-04-26 19:05:48 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-26 19:05:48 +0800 |
commit | 42df19785c22b95c5db2a65b32170d77bf39d237 (patch) | |
tree | c085fc1b7bb38ee572455113f42a5f92fb576ac5 | |
parent | dad5d712c4a5dec68a9d9a3ffb8cadbf8392bb74 (diff) | |
download | dexon-42df19785c22b95c5db2a65b32170d77bf39d237.tar.gz dexon-42df19785c22b95c5db2a65b32170d77bf39d237.tar.zst dexon-42df19785c22b95c5db2a65b32170d77bf39d237.zip |
core: vm: implement transferNodeOwnershipByFoundation (#399)
-rw-r--r-- | core/vm/oracle_contract_abi.go | 18 | ||||
-rw-r--r-- | core/vm/oracle_contracts.go | 41 | ||||
-rw-r--r-- | core/vm/oracle_contracts_test.go | 34 |
3 files changed, 93 insertions, 0 deletions
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go index 35d0f16d1..0516f3891 100644 --- a/core/vm/oracle_contract_abi.go +++ b/core/vm/oracle_contract_abi.go @@ -961,6 +961,24 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { + "name": "OldOwner", + "type": "address" + }, + { + "name": "NewOwner", + "type": "address" + } + ], + "name": "transferNodeOwnershipByFoundation", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "name": "NewPublicKey", "type": "bytes" } diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go index 35a9e5861..3a84015b5 100644 --- a/core/vm/oracle_contracts.go +++ b/core/vm/oracle_contracts.go @@ -2302,6 +2302,15 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return g.transferNodeOwnership(newOwner) + case "transferNodeOwnershipByFoundation": + args := struct { + OldOwner common.Address + NewOwner common.Address + }{} + if err := method.Inputs.Unpack(&args, arguments); err != nil { + return nil, errExecutionReverted + } + return g.transferNodeOwnershipByFoundation(args.OldOwner, args.NewOwner) case "unstake": amount := new(big.Int) if err := method.Inputs.Unpack(&amount, arguments); err != nil { @@ -2681,6 +2690,38 @@ func (g *GovernanceContract) transferNodeOwnership(newOwner common.Address) ([]b return nil, nil } +func (g *GovernanceContract) transferNodeOwnershipByFoundation(oldOwner, newOwner common.Address) ([]byte, error) { + // Only owner can update configuration. + if g.contract.Caller() != g.state.Owner() { + return nil, errExecutionReverted + } + + if newOwner == (common.Address{}) { + return nil, errExecutionReverted + } + + offset := g.state.NodesOffsetByAddress(oldOwner) + if offset.Cmp(big.NewInt(0)) < 0 { + return nil, errExecutionReverted + } + + newOffset := g.state.NodesOffsetByAddress(newOwner) + if newOffset.Cmp(big.NewInt(0)) >= 0 { + return nil, errExecutionReverted + } + + node := g.state.Node(offset) + g.state.DeleteNodeOffsets(node) + + node.Owner = newOwner + g.state.PutNodeOffsets(node, offset) + g.state.UpdateNode(offset, node) + + g.state.emitNodeOwnershipTransfered(oldOwner, newOwner) + + return nil, nil +} + func (g *GovernanceContract) replaceNodePublicKey(newPublicKey []byte) ([]byte, error) { caller := g.contract.Caller() diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go index 94c2828ad..c77313ba7 100644 --- a/core/vm/oracle_contracts_test.go +++ b/core/vm/oracle_contracts_test.go @@ -323,6 +323,40 @@ func (g *OracleContractsTestSuite) TestTransferNodeOwnership() { g.Require().Error(err) } +func (g *OracleContractsTestSuite) TestTransferNodeOwnershipByFoundation() { + privKey, addr := newPrefundAccount(g.stateDB) + pk := crypto.FromECDSAPub(&privKey.PublicKey) + + amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6)) + input, err := GovernanceABI.ABI.Pack("register", pk, "Test1", "test1@dexon.org", "Taipei", "https://dexon.org") + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, addr, input, amount) + g.Require().NoError(err) + + _, newAddr := newPrefundAccount(g.stateDB) + + // Call with not valid new owner. + input, err = GovernanceABI.ABI.Pack("transferNodeOwnershipByFoundation", common.Address{}, newAddr) + g.Require().NoError(err) + _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) + g.Require().NotNil(err) + + input, err = GovernanceABI.ABI.Pack("transferNodeOwnershipByFoundation", addr, newAddr) + g.Require().NoError(err) + + // Call with gov owner. + _, noneOwner := newPrefundAccount(g.stateDB) + _, err = g.call(GovernanceContractAddress, noneOwner, input, big.NewInt(0)) + g.Require().Error(err) + + // Call with gov owner. + _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0)) + g.Require().NoError(err) + g.Require().Equal(-1, int(g.s.NodesOffsetByAddress(addr).Int64())) + g.Require().Equal(0, int(g.s.NodesOffsetByNodeKeyAddress(addr).Int64())) + g.Require().Equal(0, int(g.s.NodesOffsetByAddress(newAddr).Int64())) +} + func (g *OracleContractsTestSuite) TestReplaceNodePublicKey() { privKey, addr := newPrefundAccount(g.stateDB) pk := crypto.FromECDSAPub(&privKey.PublicKey) |