Last active
October 19, 2020 18:49
-
-
Save nambrot/816fb1cfd71fc3df45844889d37a2d8e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/packages/protocol/contracts/common/FixidityLib.sol b/packages/protocol/contracts/common/FixidityLib.sol | |
index e5ad4d1b4..15fd8f08f 100644 | |
--- a/packages/protocol/contracts/common/FixidityLib.sol | |
+++ b/packages/protocol/contracts/common/FixidityLib.sol | |
@@ -19,6 +19,14 @@ library FixidityLib { | |
uint256 value; | |
} | |
+ /** | |
+ * @notice Returns the storage, major, minor, and patch version of the contract. | |
+ * @return The storage, major, minor, and patch version of the contract. | |
+ */ | |
+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { | |
+ return (1, 1, 1, 0); | |
+ } | |
+ | |
/** | |
* @notice Number of positions that the comma is shifted to the right. | |
*/ | |
diff --git a/packages/protocol/contracts/common/MetaTransactionWallet.sol b/packages/protocol/contracts/common/MetaTransactionWallet.sol | |
index 9de5fddc3..e3c5f96ba 100644 | |
--- a/packages/protocol/contracts/common/MetaTransactionWallet.sol | |
+++ b/packages/protocol/contracts/common/MetaTransactionWallet.sol | |
@@ -56,7 +56,7 @@ contract MetaTransactionWallet is | |
* @return The storage, major, minor, and patch version of the contract. | |
*/ | |
function getVersionNumber() public pure returns (uint256, uint256, uint256, uint256) { | |
- return (1, 1, 0, 0); | |
+ return (1, 1, 0, 1); | |
} | |
/** | |
@@ -64,6 +64,7 @@ contract MetaTransactionWallet is | |
* @param _signer The address authorized to execute transactions via this wallet. | |
*/ | |
function initialize(address _signer) external initializer { | |
+ _transferOwnership(msg.sender); | |
setSigner(_signer); | |
setEip712DomainSeparator(); | |
// MetaTransactionWallet owns itself, which necessitates that all onlyOwner functions | |
@@ -108,6 +109,32 @@ contract MetaTransactionWallet is | |
emit EIP712DomainSeparatorSet(eip712DomainSeparator); | |
} | |
+ /** | |
+ * @notice Returns the struct hash of the MetaTransaction | |
+ * @param destination The address to which the meta-transaction is to be sent. | |
+ * @param value The CELO value to be sent with the meta-transaction. | |
+ * @param data The data to be sent with the meta-transaction. | |
+ * @param _nonce The nonce for this meta-transaction local to this wallet. | |
+ * @return The digest of the provided meta-transaction. | |
+ */ | |
+ function _getMetaTransactionStructHash( | |
+ address destination, | |
+ uint256 value, | |
+ bytes memory data, | |
+ uint256 _nonce | |
+ ) internal view returns (bytes32) { | |
+ return | |
+ keccak256( | |
+ abi.encode( | |
+ EIP712_EXECUTE_META_TRANSACTION_TYPEHASH, | |
+ destination, | |
+ value, | |
+ keccak256(data), | |
+ _nonce | |
+ ) | |
+ ); | |
+ } | |
+ | |
/** | |
* @notice Returns the digest of the provided meta-transaction, to be signed by `sender`. | |
* @param destination The address to which the meta-transaction is to be sent. | |
@@ -122,16 +149,8 @@ contract MetaTransactionWallet is | |
bytes memory data, | |
uint256 _nonce | |
) public view returns (bytes32) { | |
- bytes32 structHash = keccak256( | |
- abi.encode( | |
- EIP712_EXECUTE_META_TRANSACTION_TYPEHASH, | |
- destination, | |
- value, | |
- keccak256(data), | |
- _nonce | |
- ) | |
- ); | |
- return keccak256(abi.encodePacked("\x19\x01", eip712DomainSeparator, structHash)); | |
+ bytes32 structHash = _getMetaTransactionStructHash(destination, value, data, _nonce); | |
+ return Signatures.toEthSignedTypedDataHash(eip712DomainSeparator, structHash); | |
} | |
/** | |
@@ -154,8 +173,8 @@ contract MetaTransactionWallet is | |
bytes32 r, | |
bytes32 s | |
) public view returns (address) { | |
- bytes32 digest = getMetaTransactionDigest(destination, value, data, _nonce); | |
- return Signatures.getSignerOfMessageHash(digest, v, r, s); | |
+ bytes32 structHash = _getMetaTransactionStructHash(destination, value, data, _nonce); | |
+ return Signatures.getSignerOfTypedDataHash(eip712DomainSeparator, structHash, v, r, s); | |
} | |
/** | |
diff --git a/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol b/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol | |
new file mode 100644 | |
index 000000000..0f1dd510d | |
--- /dev/null | |
+++ b/packages/protocol/contracts/common/MetaTransactionWalletDeployer.sol | |
@@ -0,0 +1,99 @@ | |
+pragma solidity ^0.5.13; | |
+import "openzeppelin-solidity/contracts/math/SafeMath.sol"; | |
+import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; | |
+import "solidity-bytes-utils/contracts/BytesLib.sol"; | |
+ | |
+import "./interfaces/ICeloVersionedContract.sol"; | |
+import "./interfaces/IMetaTransactionWalletDeployer.sol"; | |
+import "./proxies/MetaTransactionWalletProxy.sol"; | |
+import "./ExternalCall.sol"; | |
+import "./Initializable.sol"; | |
+import "./MetaTransactionWallet.sol"; | |
+ | |
+contract MetaTransactionWalletDeployer is | |
+ IMetaTransactionWalletDeployer, | |
+ ICeloVersionedContract, | |
+ Initializable, | |
+ Ownable | |
+{ | |
+ using SafeMath for uint256; | |
+ using BytesLib for bytes; | |
+ | |
+ mapping(address => address) public wallets; | |
+ mapping(address => bool) public canDeploy; | |
+ | |
+ event WalletDeployed(address indexed owner, address indexed wallet, address implementation); | |
+ event DeployerStatusGranted(address indexed addr); | |
+ event DeployerStatusRevoked(address indexed addr); | |
+ | |
+ /** | |
+ * @dev Verifies that the sender is allowed to deploy a wallet | |
+ */ | |
+ modifier onlyCanDeploy() { | |
+ require(msg.sender == owner() || canDeploy[msg.sender], "sender not allowed to deploy wallet"); | |
+ _; | |
+ } | |
+ | |
+ /** | |
+ * @notice Returns the storage, major, minor, and patch version of the contract. | |
+ * @return The storage, major, minor, and patch version of the contract. | |
+ */ | |
+ function getVersionNumber() public pure returns (uint256, uint256, uint256, uint256) { | |
+ return (1, 1, 0, 0); | |
+ } | |
+ | |
+ /** | |
+ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. | |
+ * @param initialDeployers a list of addresses that are allowed to deploy wallets | |
+ */ | |
+ function initialize(address[] calldata initialDeployers) external initializer { | |
+ _transferOwnership(msg.sender); | |
+ for (uint256 i = 0; i < initialDeployers.length; i++) { | |
+ _changeDeployerPermission(initialDeployers[i], true); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * @notice Change the permission of an address to deploy | |
+ * @param target The address to be allowed as a deployer | |
+ * @param allowedToDeploy toggle whether the address is allowed or not | |
+ */ | |
+ function changeDeployerPermission(address target, bool allowedToDeploy) external onlyOwner { | |
+ _changeDeployerPermission(target, allowedToDeploy); | |
+ } | |
+ | |
+ /** | |
+ * @notice Implementation of permission change | |
+ * @param target The address to be allowed as a deployer | |
+ * @param allowedToDeploy toggle whether the address is allowed or not | |
+ */ | |
+ function _changeDeployerPermission(address target, bool allowedToDeploy) internal { | |
+ canDeploy[target] = allowedToDeploy; | |
+ if (allowedToDeploy) { | |
+ emit DeployerStatusGranted(target); | |
+ } else { | |
+ emit DeployerStatusRevoked(target); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * @notice Used to deploy a MetaTransactionWalletProxy, set the implementation, | |
+ * initialize, transfer ownership and emit an event. | |
+ * @param owner The external account which will act as signer and owner of the proxy | |
+ * @param implementation The address of the implementation which the proxy will point to | |
+ * @param initCallData calldata pointing to a method on implementation used to initialize | |
+ */ | |
+ function deploy(address owner, address implementation, bytes calldata initCallData) | |
+ external | |
+ onlyCanDeploy | |
+ { | |
+ require(wallets[owner] == address(0), "wallet already deployed"); | |
+ | |
+ MetaTransactionWalletProxy proxy = new MetaTransactionWalletProxy(); | |
+ proxy._setAndInitializeImplementation(implementation, initCallData); | |
+ proxy._transferOwnership(owner); | |
+ wallets[owner] = address(proxy); | |
+ | |
+ emit WalletDeployed(owner, address(proxy), implementation); | |
+ } | |
+} | |
diff --git a/packages/protocol/contracts/common/Signatures.sol b/packages/protocol/contracts/common/Signatures.sol | |
index 8a57aaa11..16dec10c5 100644 | |
--- a/packages/protocol/contracts/common/Signatures.sol | |
+++ b/packages/protocol/contracts/common/Signatures.sol | |
@@ -8,7 +8,7 @@ library Signatures { | |
* @return The storage, major, minor, and patch version of the contract. | |
*/ | |
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { | |
- return (1, 1, 1, 0); | |
+ return (1, 1, 2, 0); | |
} | |
/** | |
@@ -49,4 +49,44 @@ library Signatures { | |
bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(messageHash); | |
return ECDSA.recover(prefixedHash, signature); | |
} | |
+ | |
+ /** | |
+ * @notice Given a domain separator and a structHash, construct the typed data hash | |
+ * @param eip712DomainSeparator Context specific domain separator | |
+ * @param structHash hash of the typed data struct | |
+ * @return The EIP712 typed data hash | |
+ */ | |
+ function toEthSignedTypedDataHash(bytes32 eip712DomainSeparator, bytes32 structHash) | |
+ public | |
+ pure | |
+ returns (bytes32) | |
+ { | |
+ return keccak256(abi.encodePacked("\x19\x01", eip712DomainSeparator, structHash)); | |
+ } | |
+ | |
+ /** | |
+ * @notice Given a domain separator and a structHash and a signature return the signer | |
+ * @param eip712DomainSeparator Context specific domain separator | |
+ * @param structHash hash of the typed data struct | |
+ * @param v The recovery id of the incoming ECDSA signature. | |
+ * @param r Output value r of the ECDSA signature. | |
+ * @param s Output value s of the ECDSA signature. | |
+ */ | |
+ function getSignerOfTypedDataHash( | |
+ bytes32 eip712DomainSeparator, | |
+ bytes32 structHash, | |
+ uint8 v, | |
+ bytes32 r, | |
+ bytes32 s | |
+ ) public pure returns (address) { | |
+ bytes memory signature = new bytes(65); | |
+ // Concatenate (r, s, v) into signature. | |
+ assembly { | |
+ mstore(add(signature, 32), r) | |
+ mstore(add(signature, 64), s) | |
+ mstore8(add(signature, 96), v) | |
+ } | |
+ bytes32 prefixedHash = toEthSignedTypedDataHash(eip712DomainSeparator, structHash); | |
+ return ECDSA.recover(prefixedHash, signature); | |
+ } | |
} | |
diff --git a/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol b/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol | |
new file mode 100644 | |
index 000000000..58e9abbd9 | |
--- /dev/null | |
+++ b/packages/protocol/contracts/common/interfaces/IMetaTransactionWalletDeployer.sol | |
@@ -0,0 +1,8 @@ | |
+pragma solidity ^0.5.3; | |
+ | |
+interface IMetaTransactionWalletDeployer { | |
+ function deploy(address, address, bytes calldata) external; | |
+ function changeDeployerPermission(address, bool) external; | |
+ function canDeploy(address) external view returns (bool); | |
+ function wallets(address) external view returns (address); | |
+} | |
diff --git a/packages/protocol/contracts/common/proxies/FixidityLibProxy.sol b/packages/protocol/contracts/common/proxies/FixidityLibProxy.sol | |
new file mode 100644 | |
index 000000000..41424ca89 | |
--- /dev/null | |
+++ b/packages/protocol/contracts/common/proxies/FixidityLibProxy.sol | |
@@ -0,0 +1,6 @@ | |
+pragma solidity ^0.5.3; | |
+ | |
+import "../Proxy.sol"; | |
+ | |
+/* solhint-disable no-empty-blocks */ | |
+contract FixidityLibProxy is Proxy {} | |
diff --git a/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol b/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol | |
new file mode 100644 | |
index 000000000..b6564ffff | |
--- /dev/null | |
+++ b/packages/protocol/contracts/common/proxies/MetaTransactionWalletDeployerProxy.sol | |
@@ -0,0 +1,6 @@ | |
+pragma solidity ^0.5.3; | |
+ | |
+import "../Proxy.sol"; | |
+ | |
+/* solhint-disable no-empty-blocks */ | |
+contract MetaTransactionWalletDeployerProxy is Proxy {} | |
diff --git a/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol b/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol | |
new file mode 100644 | |
index 000000000..dc7ba7a4e | |
--- /dev/null | |
+++ b/packages/protocol/contracts/common/proxies/MetaTransactionWalletProxy.sol | |
@@ -0,0 +1,6 @@ | |
+pragma solidity ^0.5.3; | |
+ | |
+import "../Proxy.sol"; | |
+ | |
+/* solhint-disable no-empty-blocks */ | |
+contract MetaTransactionWalletProxy is Proxy {} | |
diff --git a/packages/protocol/contracts/stability/Exchange.sol b/packages/protocol/contracts/stability/Exchange.sol | |
index de3b0addc..0b80bcd00 100644 | |
--- a/packages/protocol/contracts/stability/Exchange.sol | |
+++ b/packages/protocol/contracts/stability/Exchange.sol | |
@@ -294,10 +294,10 @@ contract Exchange is | |
} | |
/** | |
- * @notice Returns the sell token and buy token bucket sizes, in order. The ratio of | |
+ * @notice Returns the buy token and sell token bucket sizes, in order. The ratio of | |
* the two also represents the exchange rate between the two. | |
* @param sellGold `true` if gold is the sell token. | |
- * @return (sellTokenBucket, buyTokenBucket) | |
+ * @return (buyTokenBucket, sellTokenBucket) | |
*/ | |
function _getBuyAndSellBuckets(bool sellGold) private view returns (uint256, uint256) { | |
if (sellGold) { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ran
git diff celo-core-contracts-v1.rc1 packages/protocol/contracts
fromcelo-core-contracts-v2.pre-audit