Skip to content

Commit

Permalink
🌊 Setup contracts-watr deployment (#1251)
Browse files Browse the repository at this point in the history
  • Loading branch information
abam-iksde authored Apr 14, 2023
1 parent 3fa4b4e commit b819e25
Show file tree
Hide file tree
Showing 16 changed files with 266 additions and 43 deletions.
20 changes: 20 additions & 0 deletions packages/contracts-watr/contracts/TokenControllerV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {IRegistry} from "./interface/IRegistry.sol";
import {IOwnedUpgradeabilityProxy} from "./interface/IOwnedUpgradeabilityProxy.sol";
import {ITrueCurrency} from "./interface/ITrueCurrency.sol";
import {IProofOfReserveToken} from "./interface/IProofOfReserveToken.sol";
import {IClaimableOwnable} from "./interface/IClaimableOwnable.sol";

/** @title TokenController
* @dev This contract allows us to split ownership of the TrueCurrency contract
Expand Down Expand Up @@ -183,6 +184,12 @@ contract TokenControllerV3 {
_;
}

function initialize() external {
require(!initialized, "already initialized");
owner = msg.sender;
initialized = true;
}

/**
* @dev Modifier throws if called by any account other than proofOfReserveEnabler or owner.
*/
Expand All @@ -209,6 +216,19 @@ contract TokenControllerV3 {
pendingOwner = address(0);
}

/*
========================================
token ownership
========================================
*/
function transferTrueCurrencyOwnership(address _newOwner) external onlyOwner {
IClaimableOwnable(address(token)).transferOwnership(_newOwner);
}

function claimTrueCurrencyOwnership() public onlyOwner {
IClaimableOwnable(address(token)).claimOwnership();
}

/*
========================================
proxy functions
Expand Down
6 changes: 6 additions & 0 deletions packages/contracts-watr/contracts/TrueCurrency.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ abstract contract TrueCurrency is BurnableTokenWithBounds {
*/
event Mint(address indexed to, uint256 value);

function initialize() external {
require(!initialized, "already initialized");
owner = msg.sender;
initialized = true;
}

/**
* @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
Expand Down
7 changes: 4 additions & 3 deletions packages/contracts-watr/contracts/common/ClaimableOwnable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
pragma solidity 0.6.10;

import {ProxyStorage} from "./ProxyStorage.sol";
import {IClaimableOwnable} from "../interface/IClaimableOwnable.sol";

/**
* @title ClamableOwnable
* @dev The ClamableOwnable contract is a copy of Claimable Contract by Zeppelin.
* and provides basic authorization control functions. Inherits storage layout of
* ProxyStorage.
*/
contract ClaimableOwnable is ProxyStorage {
contract ClaimableOwnable is ProxyStorage, IClaimableOwnable {
/**
* @dev emitted when ownership is transferred
* @param previousOwner previous owner of this contract
Expand Down Expand Up @@ -46,14 +47,14 @@ contract ClaimableOwnable is ProxyStorage {
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) external onlyOwner {
function transferOwnership(address newOwner) external override onlyOwner {
pendingOwner = newOwner;
}

/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() external onlyPendingOwner {
function claimOwnership() external override onlyPendingOwner {
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.6.10;

interface IClaimableOwnable {
function claimOwnership() external;

function transferOwnership(address newOwner) external;
}
6 changes: 0 additions & 6 deletions packages/contracts-watr/contracts/mocks/MockTrueCurrency.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ contract MockTrueCurrency is TrueCurrencyWithProofOfReserve {
uint8 constant DECIMALS = 18;
uint8 constant ROUNDING = 2;

function initialize() external {
require(!initialized);
owner = msg.sender;
initialized = true;
}

function decimals() public pure override returns (uint8) {
return DECIMALS;
}
Expand Down
6 changes: 0 additions & 6 deletions packages/contracts-watr/contracts/mocks/RegistryMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,4 @@ contract RegistryMock is Registry {
owner = msg.sender;
emit OwnershipTransferred(address(0), owner);
}

function initialize() public {
require(!initialized, "already initialized");
owner = msg.sender;
initialized = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ interface HasOwner {
contract TokenControllerMock is TokenControllerV3 {
event TransferChild(address indexed child, address indexed newOwner);

// initalize controller. useful for tests
function initialize() external {
require(!initialized, "already initialized");
owner = msg.sender;
initialized = true;
}

// initialize with paramaters. useful for tests
// sets initial paramaters on testnet
function initializeWithParams(TrueCurrency _token, Registry _registry) external {
Expand Down
6 changes: 6 additions & 0 deletions packages/contracts-watr/contracts/test/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ contract Registry {
event StartSubscription(bytes32 indexed attribute, RegistryClone indexed subscriber);
event StopSubscription(bytes32 indexed attribute, RegistryClone indexed subscriber);

function initialize() external {
require(!initialized, "already initialized");
owner = msg.sender;
initialized = true;
}

// Allows a write if either a) the writer is that Registry's owner, or
// b) the writer is writing to attribute foo and that writer already has
// the canWriteTo-foo attribute set (in that same Registry)
Expand Down
5 changes: 3 additions & 2 deletions packages/contracts-watr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
"prebuild": "yarn clean",
"build:hardhat": "hardhat compile",
"build:typechain": "typechain --target ethers-v5 --out-dir build/types 'build/*.json'",
"build": "yarn build:hardhat && yarn build:typechain && mars",
"build:canary": "git log --pretty=format:'%H' -n 1 > ./build/canary.hash",
"build": "yarn build:hardhat && yarn build:typechain && mars && yarn build:canary",
"preflatten": "rm -rf custom_flatten",
"flatten": "waffle flatten .waffle.json",
"test": "mocha 'test/**/*.test.ts'",
"checks": "yarn lint && yarn test",
"deploy": "./utils/bash/marsDeploy.sh"
"deploy": "./utils/bash/marsDeploy.sh scripts/deployment/deploy.ts"
},
"dependencies": {
"ethereum-mars": "^0.2.6-dev.eb75a27",
Expand Down
27 changes: 21 additions & 6 deletions packages/contracts-watr/scripts/deployment/baseDeployment.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import {contract, createProxy, ExecuteOptions} from "ethereum-mars";
import {OwnedUpgradeabilityProxy, TokenControllerV3} from "../../build/artifacts";
import { TrueUSD } from '../../build/artifacts'
import { deployToken } from './deployToken'
import { deployTokenController, setupTokenController } from './deployTokenController'
import { deployRegistry } from './deployRegistry'

export function baseDeployment(deployer: string, options: ExecuteOptions) {
const proxy = createProxy(OwnedUpgradeabilityProxy)
export function baseDeployment() {
const {
implementation: tokenControllerImplementation,
proxy: tokenControllerProxy,
} = deployTokenController()

const tokenControllerImplementation = contract(TokenControllerV3)
const tokenControllerProxy = proxy(tokenControllerImplementation)
const { implementation: trueUSDImplementation, proxy: trueUSDProxy } = deployToken(TrueUSD, tokenControllerProxy)

const {
implementation: registryImplementation,
proxy: registryProxy,
} = deployRegistry()

setupTokenController(tokenControllerProxy, trueUSDProxy, registryProxy)

return {
trueUSDImplementation,
trueUSDProxy,
tokenControllerImplementation,
tokenControllerProxy,
registryImplementation,
registryProxy,
}
}
6 changes: 3 additions & 3 deletions packages/contracts-watr/scripts/deployment/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {deploy} from "ethereum-mars";
import {baseDeployment} from "./baseDeployment";
import { deploy } from 'ethereum-mars'
import { baseDeployment } from './baseDeployment'

deploy({ verify: true }, baseDeployment)
deploy({ verify: false }, baseDeployment)
16 changes: 16 additions & 0 deletions packages/contracts-watr/scripts/deployment/deployRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { contract, createProxy } from 'ethereum-mars'
import { OwnedUpgradeabilityProxy, Registry } from '../../build/artifacts'

export function deployRegistry() {
const ownedUpgradabilityProxy = createProxy(OwnedUpgradeabilityProxy)

const implementation = contract(Registry)
const proxy = ownedUpgradabilityProxy(implementation, (registry) => {
registry.initialize()
})

return {
implementation,
proxy,
}
}
25 changes: 25 additions & 0 deletions packages/contracts-watr/scripts/deployment/deployToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AddressLike, ArtifactFrom, contract, createProxy, Transaction, TransactionOverrides } from 'ethereum-mars'
import { OwnedUpgradeabilityProxy } from '../../build/artifacts'
import { NoParams } from 'ethereum-mars/build/src/syntax/contract'

type Token = NoParams & {
initialize(options?: TransactionOverrides): Transaction,
transferOwnership(newOwner: AddressLike, options?: TransactionOverrides): Transaction,
}

export function deployToken<T extends Token>(tokenArtifact: ArtifactFrom<T>, controller: AddressLike) {
const implementation = contract(tokenArtifact)
const tokenProxy = createProxy(OwnedUpgradeabilityProxy, (proxy) => {
proxy.upgradeTo(implementation)
proxy.transferProxyOwnership(controller)
})
const proxy = tokenProxy(implementation, (token) => {
token.initialize()
token.transferOwnership(controller)
})

return {
implementation,
proxy,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { AddressLike, contract, createProxy } from 'ethereum-mars'
import { OwnedUpgradeabilityProxy, TokenControllerV3 } from '../../build/artifacts'

export function deployTokenController() {
const ownedUpgradabilityProxy = createProxy(OwnedUpgradeabilityProxy)

const implementation = contract(TokenControllerV3)
const proxy = ownedUpgradabilityProxy(implementation, (controller) => {
controller.initialize()
})

return {
implementation,
proxy,
}
}

export function setupTokenController(controller: ReturnType<typeof deployTokenController>['proxy'], token: AddressLike, registry: AddressLike) {
controller.setRegistry(registry)
controller.setToken(token)
controller.claimTrueCurrencyProxyOwnership()
controller.claimTrueCurrencyOwnership()
}
55 changes: 55 additions & 0 deletions packages/contracts-watr/test/verifyDeployment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Contract } from 'ethers'
import { JsonRpcProvider } from '@ethersproject/providers'
import { expect } from 'chai'
import { unknown as deployments } from '../deployments-watr_local.json'

describe('verify deployment', () => {
const provider = new JsonRpcProvider('http://127.0.0.1:8822', 688)
const ownableInterface = [
'function owner() view returns (address)',
'function proxyOwner() view returns (address)',
]
const controllerInterface = [
...ownableInterface,
'function token() view returns (address)',
'function registry() view returns (address)',
]

const ownableContract = (address: string) => new Contract(
address,
controllerInterface,
provider,
)

const controllerContract = (address: string) => new Contract(
address,
controllerInterface,
provider,
)

it('controller owns currency', async () => {
const contract = ownableContract(deployments.trueUSD_proxy.address)

const owner = await contract.owner()
const proxyOwner = await contract.proxyOwner()

expect(owner).to.eq(deployments.tokenControllerV3_proxy.address)
expect(proxyOwner).to.eq(deployments.tokenControllerV3_proxy.address)
})

it('controller has currency set as token', async () => {
const contract = controllerContract(deployments.tokenControllerV3_proxy.address)

const token = await contract.token()

expect(token).to.eq(deployments.trueUSD_proxy.address)
})

it('controller has registry set correctly', async () => {
const contract = controllerContract(deployments.tokenControllerV3_proxy.address)

const token = await contract.registry()

expect(token).to.eq(deployments.registry_proxy.address)
})
})
Loading

0 comments on commit b819e25

Please sign in to comment.