Skip to content

Commit

Permalink
Support swap booster deployment (#387)
Browse files Browse the repository at this point in the history
* Support `swapBoosterDeployment`

* Code format

* Add test

* Update contract changes

* Incease `gasLimit` to fix contract deployment issue

* Update test

* Fix test

* Reuse add and remove boosterDeployment
  • Loading branch information
mzxyz authored Mar 20, 2024
1 parent 6c10cee commit 2b3ed8d
Show file tree
Hide file tree
Showing 12 changed files with 302 additions and 171 deletions.
116 changes: 90 additions & 26 deletions contracts/RewardsBooster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import './interfaces/IEraManager.sol';
import './interfaces/IStakingAllocation.sol';
import './interfaces/IStakingManager.sol';
import './interfaces/IIndexerRegistry.sol';
import './interfaces/IConsumerRegistry.sol';
import './interfaces/ISettings.sol';
import './interfaces/ISQToken.sol';
import './interfaces/IRewardsDistributor.sol';
Expand Down Expand Up @@ -162,50 +163,74 @@ contract RewardsBooster is Initializable, OwnableUpgradeable, IRewardsBooster {
}

/**
* @notice add booster deployment staking modify eraPool and deployment map
* @param _deploymentId the deployment id
* @param _amount the added amount
* @notice
* @param deploymentId project deployment id
*/
function boostDeployment(bytes32 _deploymentId, uint256 _amount) external {
modifier onlyRegisteredDeployment(bytes32 deploymentId) {
require(
IProjectRegistry(settings.getContractAddress(SQContracts.ProjectRegistry))
.isDeploymentRegistered(_deploymentId),
.isDeploymentRegistered(deploymentId),
'RB008'
);
_;
}

address boosterAccount = msg.sender;
DeploymentPool storage deploymentPool = deploymentPools[_deploymentId];
onDeploymentBoosterUpdate(_deploymentId, boosterAccount);
deploymentPool.boosterPoint += _amount;
deploymentPool.accountBooster[boosterAccount] += _amount;
deploymentPool.accRewardsPerBooster = accRewardsPerBooster;
totalBoosterPoint += _amount;

/**
* @notice add booster deployment staking modify eraPool and deployment map
* @param _deploymentId the deployment id
* @param _amount the added amount
*/
function boostDeployment(
bytes32 _deploymentId,
uint256 _amount
) external onlyRegisteredDeployment(_deploymentId) {
_addBoosterDeployment(_deploymentId, msg.sender, _amount);
IERC20(settings.getContractAddress(SQContracts.SQToken)).safeTransferFrom(
boosterAccount,
msg.sender,
address(this),
_amount
);
emit DeploymentBoosterAdded(_deploymentId, boosterAccount, _amount);
}

/**
* @notice remove booster from deployment
* @param deployment deploymentId
* @param deploymentId deploymentId
* @param amount the added amount
*/
function removeBoosterDeployment(bytes32 deployment, uint256 amount) external {
DeploymentPool storage deploymentPool = deploymentPools[deployment];
require(deploymentPool.accountBooster[msg.sender] >= amount, 'RB003');
function removeBoosterDeployment(
bytes32 deploymentId,
uint256 amount
) external {
require(deploymentPools[deploymentId].accountBooster[msg.sender] >= amount, 'RB003');
_removeBoosterDeployment(deploymentId, msg.sender, amount);
IERC20(settings.getContractAddress(SQContracts.SQToken)).safeTransfer(msg.sender, amount);
}

onDeploymentBoosterUpdate(deployment, msg.sender);
deploymentPool.boosterPoint -= amount;
deploymentPool.accountBooster[msg.sender] -= amount;
deploymentPool.accRewardsPerBooster = accRewardsPerBooster;
totalBoosterPoint -= amount;
/**
* @notice swap booster from one deployment to another
* @param account the account booster the deployments
* @param from from deploymentId
* @param to to deploymentId
* @param amount the amount to swap
*/
function swapBoosterDeployment(
address account,
bytes32 from,
bytes32 to,
uint256 amount
) external onlyRegisteredDeployment(to) {
require(from != to, 'RB013');
if (account != msg.sender) {
require(
IConsumerRegistry(settings.getContractAddress(SQContracts.ConsumerRegistry))
.isController(account, msg.sender),
'RB014'
);
}

IERC20(settings.getContractAddress(SQContracts.SQToken)).safeTransfer(msg.sender, amount);
emit DeploymentBoosterRemoved(deployment, msg.sender, amount);
require(deploymentPools[from].accountBooster[account] >= amount, 'RB003');
_removeBoosterDeployment(from, account, amount);
_addBoosterDeployment(to, account, amount);
}

function getRunnerDeploymentBooster(
Expand Down Expand Up @@ -253,6 +278,45 @@ contract RewardsBooster is Initializable, OwnableUpgradeable, IRewardsBooster {
);
}


/**
* @notice Add booster deployment staking
* @param _deploymentId the deployment id
* @param _account the booster account
* @param _amount the added amount
*/
function _addBoosterDeployment(bytes32 _deploymentId, address _account, uint256 _amount) internal {
DeploymentPool storage deploymentPool = deploymentPools[_deploymentId];
onDeploymentBoosterUpdate(_deploymentId, _account);
deploymentPool.boosterPoint += _amount;
deploymentPool.accountBooster[_account] += _amount;
deploymentPool.accRewardsPerBooster = accRewardsPerBooster;
totalBoosterPoint += _amount;

emit DeploymentBoosterAdded(_deploymentId, _account, _amount);
}

/**
* @notice Remove booster from deployment
* @param _deploymentId deploymentId
* @param _account the booster account
* @param _amount the added amount
*/
function _removeBoosterDeployment(
bytes32 _deploymentId,
address _account,
uint256 _amount
) internal {
DeploymentPool storage deploymentPool = deploymentPools[_deploymentId];
onDeploymentBoosterUpdate(_deploymentId, _account);
deploymentPool.boosterPoint -= _amount;
deploymentPool.accountBooster[_account] -= _amount;
deploymentPool.accRewardsPerBooster = accRewardsPerBooster;
totalBoosterPoint -= _amount;

emit DeploymentBoosterRemoved(_deploymentId, _account, _amount);
}

/**
* @notice Fix reward considering missed labor
* @param _reward reward before fix
Expand Down
30 changes: 29 additions & 1 deletion publish/ABI/RewardsBooster.json
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@
"inputs": [
{
"internalType": "bytes32",
"name": "deployment",
"name": "deploymentId",
"type": "bytes32"
},
{
Expand Down Expand Up @@ -1027,6 +1027,34 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bytes32",
"name": "from",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "to",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "swapBoosterDeployment",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "totalBoosterPoint",
Expand Down
2 changes: 2 additions & 0 deletions publish/revertcode.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,7 @@
"RB010": "Invalid report time when setMissedLabor",
"RB011": "MissedLaborTime exceed current report period",
"RB012": "Invalid param length to set MissedLabor",
"RB013": "Deployment ids can not be same",
"RB014": "Caller is not a controller of the account",
"OPD01": "l2token address is empty"
}
8 changes: 6 additions & 2 deletions scripts/config/contracts.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ export default {
mainnet: {
InflationController: [12000, '0x9E3a8e4d0115e5b157B61b6a5372ecc41446D472'], // inflationRate, inflationDestination
InflationDestination: ['0xd043807A0f41EE95fD66A523a93016a53456e79B'], // XcRecipient
OpDestination: ['0x09395a2A58DB45db0da254c7EAa5AC469D8bDc85', '0x858c50C3AF1913b0E849aFDB74617388a1a5340d', '0x3154Cf16ccdb4C6d922629664174b904d80F2C35'],
OpDestination: [
'0x09395a2A58DB45db0da254c7EAa5AC469D8bDc85',
'0x858c50C3AF1913b0E849aFDB74617388a1a5340d',
'0x3154Cf16ccdb4C6d922629664174b904d80F2C35',
],
SQToken: [utils.parseEther('10000000000')], // initial supply 10 billion
VTSQToken: [],
Staking: [1209600, 1e3], // lockPeriod: 14 days, unbondFeeRate: 10e3/10e6=0.001=0.1%
Expand All @@ -17,7 +21,7 @@ export default {
// base: 2s a block, 31536000/2 = 15768000 blocks a year, 1% rewards = 100000000 / 15768000 = about 6.3419584 SQT per block
RewardsBooster: [utils.parseEther('6.3419584'), utils.parseEther('1000')], // _issuancePerBlock, _minimumDeploymentBooster
L2SQToken: ['0x4200000000000000000000000000000000000010', '0x09395a2A58DB45db0da254c7EAa5AC469D8bDc85'], // l2bridge, l1token
PriceOracle: [10 , 3600],
PriceOracle: [10, 3600],
},
kepler: {
InflationController: [0, '0x34c35136ECe9CBD6DfDf2F896C6e29be01587c0C'], // inflationRate, inflationDestination
Expand Down
18 changes: 9 additions & 9 deletions scripts/config/mainnet.config.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
const config = {
multiSig: {
root: {
foundation: "0x623D1426f5F45D39A1D9EbD3A5f6abeE0c8eC469",
teamAllocation: "0x32aB17a7d990F4afA8AD01cbFcbf49c26CFC0494",
foundationAllocation: "0x16F94a7719994303125bc7cEB2Dac0Cca2e9b787",
foundation: '0x623D1426f5F45D39A1D9EbD3A5f6abeE0c8eC469',
teamAllocation: '0x32aB17a7d990F4afA8AD01cbFcbf49c26CFC0494',
foundationAllocation: '0x16F94a7719994303125bc7cEB2Dac0Cca2e9b787',
},
child: {
foundation: "0x31E99bdA5939bA2e7528707507b017f43b67F89B",
treasury: "0xd043807A0f41EE95fD66A523a93016a53456e79B",
council: "0xDD93Add934dCc40b54f3d701C5666CFf1C9FD0Df",
}
}
}
foundation: '0x31E99bdA5939bA2e7528707507b017f43b67F89B',
treasury: '0xd043807A0f41EE95fD66A523a93016a53456e79B',
council: '0xDD93Add934dCc40b54f3d701C5666CFf1C9FD0Df',
},
},
};

export default config;
2 changes: 1 addition & 1 deletion scripts/deployContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ async function getOverrides(): Promise<Overrides> {
const price = await wallet.provider.getGasPrice();
// console.log(`gasprice: ${price.toString()}`)
// price = price.add(15000000000); // add extra 15 gwei
return { gasPrice: price, gasLimit: 3000000 };
return { gasPrice: price };
}

export function saveDeployment(name: string, deployment: Partial<ContractDeployment>) {
Expand Down
8 changes: 1 addition & 7 deletions scripts/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,7 @@ export async function airdrop(sdk: ContractSDK, _provider?: StaticJsonRpcProvide

async function rootContractOwnerTransfer(sdk: RootContractSDK) {
logger = getLogger('Owner Transfer');
const contracts = [
sdk.sqToken,
sdk.vtSQToken,
sdk.vesting,
sdk.inflationDestination,
];
const contracts = [sdk.sqToken, sdk.vtSQToken, sdk.vesting, sdk.inflationDestination];

const foundation = mainnetConfig.multiSig.root.foundation;
logger.info(`Transfer Ownership to ${foundation}`);
Expand All @@ -214,7 +209,6 @@ async function rootContractOwnerTransfer(sdk: RootContractSDK) {

// TODO: please manually transfer the ownership of `proxyAdmin` | `settings` | `infaltionController` to `mainnetConfig.multiSig.root.foundationAllocation;`
}


export async function childContractOwnerTransfer(sdk: ContractSDK) {
logger = getLogger('Owner Transfer');
Expand Down
9 changes: 3 additions & 6 deletions scripts/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ async function checkRootInitialisation(sdk: RootContractSDK, config) {
logger.info(`InflationRate to be equal ${rate}`);
expect((await sdk.inflationController.inflationRate()).toNumber()).to.eq(rate);
logger.info(`InflationDestination to be equal ${destination}`);
expect((await sdk.inflationController.inflationDestination()).toUpperCase()).to.equal(
destination.toUpperCase()
);
expect((await sdk.inflationController.inflationDestination()).toUpperCase()).to.equal(destination.toUpperCase());
logger.info('🎉 InflationController Contract verified\n');

// inflation destination
Expand All @@ -57,7 +55,7 @@ async function checkRootInitialisation(sdk: RootContractSDK, config) {
expect(totalSupply).to.eql(amount);
logger.info(`SQToken minter is ${sdk.inflationController.address}`);
// TODO: update this check after TGE launched
expect((await sdk.sqToken.getMinter())).to.equal('0x0000000000000000000000000000000000000000');
expect(await sdk.sqToken.getMinter()).to.equal('0x0000000000000000000000000000000000000000');
const wallet = mainnetConfig.multiSig.root.foundation;
logger.info(`Foundation wallet: ${wallet} own the total assets`);
const foundationSQTBalance = await sdk.sqToken.balanceOf(wallet);
Expand Down Expand Up @@ -172,7 +170,6 @@ async function checkChildInitialisation(sdk: ContractSDK, config, caller: string
logger.info(`blockLimit to be equal ${blockLimit}`);
expect(await sdk.priceOracle.blockLimit()).to.eql(BN(blockLimit));
logger.info('🎉 PriceOracle Contract verified\n');

} catch (err) {
logger.info(`Failed to verify contract: ${err}`);
}
Expand Down Expand Up @@ -246,7 +243,7 @@ async function checkRootContractsOwnership(sdk: RootContractSDK) {
[sdk.inflationController, foundationW],
// TODO: verify `settings` and `proxyAmdin` which owner is `allocationW`
];

try {
for (const [contract, owner] of contracts) {
// @ts-expect-error no owner interface
Expand Down
11 changes: 5 additions & 6 deletions src/rootSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@ export class RootContractSDK {
}

private async _init() {
const contracts = Object.entries(this._contractDeployments)
.map(([name, contract]) => ({
address: contract.address,
factory: CONTRACT_FACTORY[name as ContractName] as FactoryContstructor,
name: name as ContractName,
}));
const contracts = Object.entries(this._contractDeployments).map(([name, contract]) => ({
address: contract.address,
factory: CONTRACT_FACTORY[name as ContractName] as FactoryContstructor,
name: name as ContractName,
}));

for (const { name, factory, address } of contracts) {
if (!factory) continue;
Expand Down
Loading

0 comments on commit 2b3ed8d

Please sign in to comment.