From e06587043118ec63b96b359f2f21ddce8ce021be Mon Sep 17 00:00:00 2001 From: Danny Date: Thu, 9 Dec 2021 18:55:30 -0500 Subject: [PATCH] JBFundingCycleMetadataResolver fixes + packing util method (#38) * JBFundingCycleMetadataResolver fixes + packing util method * Address review comments --- .../JBFundingCycleMetadataResolver.sol | 64 +++++++------- test/helpers/utils.js | 88 ++++++++++++++++++- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/contracts/libraries/JBFundingCycleMetadataResolver.sol b/contracts/libraries/JBFundingCycleMetadataResolver.sol index 4c554364..ff5e9624 100644 --- a/contracts/libraries/JBFundingCycleMetadataResolver.sol +++ b/contracts/libraries/JBFundingCycleMetadataResolver.sol @@ -25,27 +25,27 @@ library JBFundingCycleMetadataResolver { } function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 56) & 1) == 0; + return ((_fundingCycle.metadata >> 56) & 1) == 1; } function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 57) & 1) == 0; + return ((_fundingCycle.metadata >> 57) & 1) == 1; } function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 58) & 1) == 0; + return ((_fundingCycle.metadata >> 58) & 1) == 1; } function mintPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 59) & 1) == 0; + return ((_fundingCycle.metadata >> 59) & 1) == 1; } function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 60) & 1) == 0; + return ((_fundingCycle.metadata >> 60) & 1) == 1; } function changeTokenAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 61) & 1) == 0; + return ((_fundingCycle.metadata >> 61) & 1) == 1; } function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle) @@ -53,7 +53,7 @@ library JBFundingCycleMetadataResolver { pure returns (bool) { - return ((_fundingCycle.metadata >> 62) & 1) == 0; + return ((_fundingCycle.metadata >> 62) & 1) == 1; } function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle) @@ -61,11 +61,11 @@ library JBFundingCycleMetadataResolver { pure returns (bool) { - return ((_fundingCycle.metadata >> 63) & 1) == 0; + return ((_fundingCycle.metadata >> 63) & 1) == 1; } function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return ((_fundingCycle.metadata >> 64) & 1) == 0; + return ((_fundingCycle.metadata >> 64) & 1) == 1; } function shouldUseLocalBalanceForRedemptions(JBFundingCycle memory _fundingCycle) @@ -73,11 +73,11 @@ library JBFundingCycleMetadataResolver { pure returns (bool) { - return ((_fundingCycle.metadata >> 65) & 1) == 0; + return ((_fundingCycle.metadata >> 65) & 1) == 1; } function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) { - return (_fundingCycle.metadata >> 66) & 1 == 0; + return (_fundingCycle.metadata >> 66) & 1 == 1; } function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle) @@ -85,7 +85,7 @@ library JBFundingCycleMetadataResolver { pure returns (bool) { - return (_fundingCycle.metadata >> 67) & 1 == 0; + return (_fundingCycle.metadata >> 67) & 1 == 1; } function dataSource(JBFundingCycle memory _fundingCycle) @@ -102,47 +102,47 @@ library JBFundingCycleMetadataResolver { @param _metadata The metadata to validate and pack. - @return packed The packed uint256 of all metadata params. The first 8 bytes specify the version. + @return packed The packed uint256 of all metadata params. The first 8 bits specify the version. */ function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata) internal pure returns (uint256 packed) { - // version 1 in the first 8 bytes. + // version 1 in the bits 0-7 (8 bits). packed = 1; - // reserved rate in bits 8-23. + // reserved rate in bits 8-23 (16 bits). packed |= _metadata.reservedRate << 8; - // bonding curve in bits 24-39. - // Redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs. + // redemption rate in bits 24-39 (16 bits). + // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs. packed |= (10000 - _metadata.redemptionRate) << 24; - // reconfiguration bonding curve rate in bits 40-55. - // Redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs. - packed |= (10000 - _metadata.ballotRedemptionRate) << 50; + // ballot redemption rate rate in bits 40-55 (16 bits). + // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs. + packed |= (10000 - _metadata.ballotRedemptionRate) << 40; // pause pay in bit 56. - packed |= (_metadata.pausePay ? 1 : 0) << 56; + if (_metadata.pausePay) packed |= 1 << 56; // pause tap in bit 57. - packed |= (_metadata.pauseDistributions ? 1 : 0) << 57; + if (_metadata.pauseDistributions) packed |= 1 << 57; // pause redeem in bit 58. - packed |= (_metadata.pauseRedeem ? 1 : 0) << 58; + if (_metadata.pauseRedeem) packed |= 1 << 58; // pause mint in bit 59. - packed |= (_metadata.pauseMint ? 1 : 0) << 59; + if (_metadata.pauseMint) packed |= 1 << 59; // pause mint in bit 60. - packed |= (_metadata.pauseBurn ? 1 : 0) << 60; + if (_metadata.pauseBurn) packed |= 1 << 60; // pause change token in bit 61. - packed |= (_metadata.allowChangeToken ? 1 : 0) << 61; + if (_metadata.allowChangeToken) packed |= 1 << 61; // allow terminal migration in bit 62. - packed |= (_metadata.allowTerminalMigration ? 1 : 0) << 62; + if (_metadata.allowTerminalMigration) packed |= 1 << 62; // allow controller migration in bit 63. - packed |= (_metadata.allowControllerMigration ? 1 : 0) << 63; + if (_metadata.allowControllerMigration) packed |= 1 << 63; // hold fees in bit 64. - packed |= (_metadata.holdFees ? 1 : 0) << 64; + if (_metadata.holdFees) packed |= 1 << 64; // useLocalBalanceForRedemptions in bit 65. - packed |= (_metadata.useLocalBalanceForRedemptions ? 1 : 0) << 65; + if (_metadata.useLocalBalanceForRedemptions) packed |= 1 << 65; // use pay data source in bit 66. - packed |= (_metadata.useDataSourceForPay ? 1 : 0) << 66; + if (_metadata.useDataSourceForPay) packed |= 1 << 66; // use redeem data source in bit 67. - packed |= (_metadata.useDataSourceForRedeem ? 1 : 0) << 67; + if (_metadata.useDataSourceForRedeem) packed |= 1 << 67; // data source address in bits 68-227. packed |= uint160(address(_metadata.dataSource)) << 68; } diff --git a/test/helpers/utils.js b/test/helpers/utils.js index bcc71047..1b65f9ea 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -1,6 +1,11 @@ import { BigNumber } from '@ethersproject/bignumber'; import { ethers, network } from 'hardhat'; +/** + * Pack array of permission indexes into BigNumber + * @param {number[]} permissionIndexes + * @return {ethers.BigNumber} + */ export function makePackedPermissions(permissionIndexes) { return permissionIndexes.reduce( (sum, i) => sum.add(ethers.BigNumber.from(2).pow(i)), @@ -8,6 +13,12 @@ export function makePackedPermissions(permissionIndexes) { ); } +/** + * Create a test account + * @param {string} address + * @param {ethers.BigNumber} balance + * @return {ethers.JsonRpcSigner} + */ export async function impersonateAccount( address, balance = BigNumber.from('0x1000000000000000000000'), @@ -22,23 +33,92 @@ export async function impersonateAccount( return await ethers.getSigner(address); } +/** + * Deploy a test JBToken contract + * @param {string} name + * @param {string} symbol + * @return {ethers.Contract} + */ export async function deployJbToken(name, symbol) { const jbTokenFactory = await ethers.getContractFactory('JBToken'); return await jbTokenFactory.deploy(name, symbol); } +/** + * Get a new date by adding days to now + * @param {number} days + * @return {date} + */ export function daysFromNow(days) { let date = new Date(); date.setDate(date.getDate() + days); return date; } - + +/** + * Get a new date by adding days to the original date + * @param {date} date + * @param {number} days + * @return {date} + */ export function daysFromDate(date, days) { let newDate = new Date(); - newDate.setDate(date.getDate() + days) + newDate.setDate(date.getDate() + days); return newDate; } - + +/** + * Get date in seconds + * @param {date} date + * @return {number} + */ export function dateInSeconds(date) { return Math.floor(date.getTime() / 1000); -} \ No newline at end of file +} + +/** + * Returns a mock FundingCyleMetadata packed into a BigNumber + * @summary Should mirror the bit logic in JBFundingCycleMetadataResolver.sol. + * @param {custom obj} e.g. packFundingCycleMetadata({ reservedRate: 3500, pausePay: 1 }) + * @return {ethers.BigNumber} + * @note Passing in an empty obj will use default values below + */ +export function packFundingCycleMetadata({ + version = 1, + reservedRate = 0, // percentage + redemptionRate = 10000, // percentage + ballotRedemptionRate = 10000, // percentage + pausePay = 0, // boolean + pauseDistributions = 0, // boolean + pauseRedeem = 0, // boolean + pauseMint = 0, // boolean + pauseBurn = 0, // boolean + allowChangeToken = 0, // boolean + allowTerminalMigration = 0, // boolean + allowControllerMigration = 0, // boolean + holdFees = 0, // boolean + useLocalBalanceForRedemptions = 0, // boolean + useDataSourceForPay = 0, // boolean + useDataSourceForRedeem = 0, // boolean + dataSource = 0, // address +} = {}) { + const one = ethers.BigNumber.from(1); + + let packed = ethers.BigNumber.from(version); + packed = packed.or(ethers.BigNumber.from(reservedRate).shl(8)); + packed = packed.or(ethers.BigNumber.from(10000 - redemptionRate).shl(24)); + packed = packed.or(ethers.BigNumber.from(10000 - ballotRedemptionRate).shl(40)); + if (pausePay) packed = packed.or(one.shl(56)); + if (pauseDistributions) packed = packed.or(one.shl(57)); + if (pauseRedeem) packed = packed.or(one.shl(58)); + if (pauseMint) packed = packed.or(one.shl(59)); + if (pauseBurn) packed = packed.or(one.shl(60)); + if (allowChangeToken) packed = packed.or(one.shl(61)); + if (allowTerminalMigration) packed = packed.or(one.shl(62)); + if (allowControllerMigration) packed = packed.or(one.shl(63)); + if (holdFees) packed = packed.or(one.shl(64)); + if (useLocalBalanceForRedemptions) packed = packed.or(one.shl(65)); + if (useDataSourceForPay) packed = packed.or(one.shl(66)); + if (useDataSourceForRedeem) packed = packed.or(one.shl(67)); + return packed.or(ethers.BigNumber.from(dataSource).shl(68)); +}