aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/vm/oracle_contract_abi.go18
-rw-r--r--core/vm/oracle_contracts.go41
-rw-r--r--core/vm/oracle_contracts_test.go34
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 4434dcf5c..47a680455 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -2300,6 +2300,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 {
@@ -2679,6 +2688,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 be1e2a27d..5be893f95 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -322,6 +322,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)