RocketDAONodeTrustedUpgrade - upgrade does not prevent the use of the same address multiple times creating an inconsistency where getContractAddress returns outdated information
When adding a new contract, it is checked whether the address is already in use. This check is missing when upgrading a named contract to a new implementation, potentially allowing someone to register one address to multiple names creating an inconsistent configuration.\\nThe crux of this is, that, `getContractAddress()` will now return a contract address that is not registered anymore (while `getContractName` may throw). `getContractAddress` can therefore not relied upon when checking ACL.\\nadd contract `name=test, address=0xfefe` ->\\n```\\n sets contract.exists.0xfefe=true\\n sets contract.name.0xfefe=test\\n sets contract.address.test=0xfefe\\n sets contract.abi.test=abi\\n```\\n\\nadd another contract `name=badcontract, address=0xbadbad` ->\\n```\\nsets contract.exists.0xbadbad=true\\nsets contract.name.0xbadbad=badcontract\\nsets contract.address.badcontract=0xbadbad\\nsets contract.abi.badcontract=abi\\n```\\n\\nupdate contract `name=test, address=0xbadbad` reusing badcontradcts address, the address is now bound to 2 names (test, badcontract)\\n```\\noverwrites contract.exists.0xbadbad=true` (even though its already true)\\nupdates contract.name.0xbadbad=test (overwrites the reference to badcontract; badcontracts config is now inconsistent)\\nupdates contract.address.test=0xbadbad (ok, expected)\\nupdates contract.abi.test=abi (ok, expected)\\nremoves contract.name.0xfefe (ok)\\nremoves contract.exists.0xfefe (ok)\\n```\\n\\nupdate contract `name=test, address=0xc0c0`\\n```\\nsets contract.exists.0xc0c0=true\\nsets contract.name.0xc0c0=test (ok, expected)\\nupdates contract.address.test=0xc0c0 (ok, expected)\\nupdates contract.abi.test=abi (ok, expected)\\nremoves contract.name.0xbadbad (the contract is still registered as badcontract, but is indirectly removed now)\\nremoves contract.exists.0xbadbad (the contract is still registered as badcontract, but is indirectly removed now)\\n```\\n\\nAfter this, `badcontract` is partially cleared, `getContractName(0xbadbad)` throws while `getContractAddress(badcontract)` returns `0xbadbad` which is already unregistered (contract.exists.0xbadbad=false)\\n```\\n(removed) contract.exists.0xbadbad\\n(removed) contract.name.0xbadbad=badcontract\\nsets contract.address.badcontract=0xbadbad\\nsets contract.abi.badcontract=abi\\n```\\n\\ncheck in `_addContract``\\n```\\nrequire(\\_contractAddress != address(0x0), "Invalid contract address");\\n```\\n\\nno checks in `upgrade.`\\n```\\nrequire(\\_contractAddress != address(0x0), "Invalid contract address");\\nrequire(\\_contractAddress != oldContractAddress, "The contract address cannot be set to its current address");\\n// Register new contract\\nsetBool(keccak256(abi.encodePacked("contract.exists", \\_contractAddress)), true);\\nsetString(keccak256(abi.encodePacked("contract.name", \\_contractAddress)), \\_name);\\nsetAddress(keccak256(abi.encodePacked("contract.address", \\_name)), \\_contractAddress);\\nsetString(keccak256(abi.encodePacked("contract.abi", \\_name)), \\_contractAbi);\\n```\\n
Resolution\\nA check has been introduced to make sure that the new contract address is not already in use by checking against the corresponding `contract.exists` storage key.\\nCheck that the address being upgraded to is not yet registered and properly clean up `contract.address.<name|abi>`.
```\\n sets contract.exists.0xfefe=true\\n sets contract.name.0xfefe=test\\n sets contract.address.test=0xfefe\\n sets contract.abi.test=abi\\n```\\n