Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "packages/hardhat/lib/forge-std"]
path = packages/hardhat/lib/forge-std
url = https://github.com/foundry-rs/forge-std
1 change: 1 addition & 0 deletions packages/hardhat/cache_forge/solidity-files-cache.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/hardhat/config/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// config/index.d.ts
export const merkleRoots: { [key: string]: string };
export const campaignCIDs: { [key: string]: string };
13 changes: 6 additions & 7 deletions packages/hardhat/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ const addresses = {
};

const merkleRoots = {
public: '0x0000000000000000000000000000000000000000000000000000000000000000',
tokensoftDevs: '0xb613dab8b7189ee0286275425d0d77df7cbb7550ba579c1a70def1b1acb931a2'
public: "0x0000000000000000000000000000000000000000000000000000000000000000",
tokensoftDevs: "0xb613dab8b7189ee0286275425d0d77df7cbb7550ba579c1a70def1b1acb931a2",
};

const campaignCIDs = {
basicSale: "Qma51yJyJBKgxLVc9feg4b9RSuMq1ynrfqs5vEZkZyC4Zi",
tokensoftDevsOnlySale: "Qma51yJyJBKgxLVc9feg4b9RSuMq1ynrfqs5vEZkZyC4Zi"
tokensoftDevsOnlySale: "Qma51yJyJBKgxLVc9feg4b9RSuMq1ynrfqs5vEZkZyC4Zi",
};

const dateTimestamps = {
Expand All @@ -28,11 +28,10 @@ const uints = {
};

const merkleData = {
rootZero: ethers.constants.HashZero, // 0x0
rootZero: ethers.ZeroHash, // 0x0
balancedTree,
simpleClaimTree: {
merkleRoot:
"0x080658a34ceaef57f8ed16606943f19b652009929c038cc578fb0ccebbc75fdc",
merkleRoot: "0x080658a34ceaef57f8ed16606943f19b652009929c038cc578fb0ccebbc75fdc",
proofs: simpleProofsArray,
},
};
Expand All @@ -43,5 +42,5 @@ module.exports = {
dateTimestamps,
uints,
merkleData,
merkleRoots
merkleRoots,
};
7 changes: 2 additions & 5 deletions packages/hardhat/config/merkleData.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ const simpleProofsArray = [
index: 1,
account: "0x8Cf384fe1810ce413CBc3A8d20a752E5a48aaDc0",
amount: 5000000000000000000000,
merkleProof: [
"0x60c928dce63da75777e33948201751a726c783a7ff46c2eab1fab21673159300",
],
merkleProof: ["0x60c928dce63da75777e33948201751a726c783a7ff46c2eab1fab21673159300"],
},
{
index: 2,
Expand All @@ -40,8 +38,7 @@ const simpleProofsArray = [
];

const balancedTree = {
merkleRoot:
"0xe117ba62b4a23109e269a2f3706c12627adc8245a6aa786804b20fa150508177",
merkleRoot: "0xe117ba62b4a23109e269a2f3706c12627adc8245a6aa786804b20fa150508177",
totalDistributionAmount: "30000000000000000000000",
"0xa4673B9e26aF90eeCe783f55eA85188c391A481C": {
index: 0,
Expand Down
5 changes: 3 additions & 2 deletions packages/hardhat/contracts/claim/BasicDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ contract BasicDistributor is AdvancedDistributor {

function getVestedFraction(
address, /*beneficiary*/
uint256 /*time*/
uint256, /*time*/
bytes memory /*data*/
) public view override returns (uint256) {
// all tokens vest immediately
return fractionDenominator;
Expand All @@ -45,7 +46,7 @@ contract BasicDistributor is AdvancedDistributor {

function claim(address beneficiary) external nonReentrant {
// effects
uint256 claimedAmount = super._executeClaim(beneficiary, records[beneficiary].total);
uint256 claimedAmount = super._executeClaim(beneficiary, records[beneficiary].total, new bytes(0));
// interactions
super._settleClaim(beneficiary, claimedAmount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ contract ContinuousVestingMerkle is ContinuousVesting, MerkleSet {
nonReentrant
{
// effects
uint256 claimedAmount = super._executeClaim(beneficiary, totalAmount);
uint256 claimedAmount = super._executeClaim(beneficiary, totalAmount, new bytes(0));
// interactions
super._settleClaim(beneficiary, claimedAmount);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import { PerAddressContinuousVesting } from './abstract/PerAddressContinuousVesting.sol';
import { MerkleSet } from './abstract/MerkleSet.sol';

contract PerAddressContinuousVestingMerkle is PerAddressContinuousVesting, MerkleSet {

constructor(
IERC20 _token, // the token being claimed
uint256 _total, // the total claimable by all users
string memory _uri, // information on the sale (e.g. merkle proofs)
uint256 _voteFactor, // votes have this weight
bytes32 _merkleRoot, // the merkle root for claim membership (also used as salt for the fair queue delay time),
uint160 _maxDelayTime // the maximum delay time for the fair queue
)
PerAddressContinuousVesting(
_token,
_total,
_uri,
_voteFactor,
_maxDelayTime,
uint160(uint256(_merkleRoot))
)
MerkleSet(_merkleRoot)
{}

function NAME() external pure override returns (string memory) {
return 'PerAddressContinuousVestingMerkle';
}

function VERSION() external pure override returns (uint256) {
return 4;
}

function initializeDistributionRecord(
uint256 index, // the beneficiary's index in the merkle root
address beneficiary, // the address that will receive tokens
uint256 amount, // the total claimable by this beneficiary
uint256 start, // the start of the vesting period
uint256 cliff, // cliff time
uint256 end, // the end of the vesting period
bytes32[] calldata merkleProof
)
external
validMerkleProof(keccak256(abi.encodePacked(index, beneficiary, amount, start, cliff, end)), merkleProof)
{
_initializeDistributionRecord(beneficiary, amount);
}

function claim(
uint256 index, // the beneficiary's index in the merkle root
address beneficiary, // the address that will receive tokens
uint256 totalAmount, // the total claimable by this beneficiary
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto - this doesn't seem right: need to put continuous vesting parameters (start, cliff, end) in every function that checks merkle proof since they are required to generate the leaf.

uint256 start, // the start of the vesting period
uint256 cliff, // cliff time
uint256 end, // the end of the vesting period
bytes32[] calldata merkleProof
)
external
validMerkleProof(keccak256(abi.encodePacked(index, beneficiary, totalAmount, start, cliff, end)), merkleProof)
nonReentrant
{
// effects
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount, new bytes(0));
// interactions
_settleClaim(beneficiary, claimedAmount);
}

function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner {
_setMerkleRoot(_merkleRoot);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import { PerAddressTrancheVesting, Tranche } from './abstract/PerAddressTrancheVesting.sol';
import { MerkleSet } from './abstract/MerkleSet.sol';

contract PerAddressTrancheVestingMerkle is PerAddressTrancheVesting, MerkleSet {
constructor(
IERC20 _token,
uint256 _total,
string memory _uri, // information on the sale (e.g. merkle proofs)
uint256 _voteFactor,
bytes32 _merkleRoot,
uint160 _maxDelayTime // the maximum delay time for the fair queue
)
PerAddressTrancheVesting(
_token,
_total,
_uri,
_voteFactor,
_maxDelayTime,
uint160(uint256(_merkleRoot))
)
MerkleSet(_merkleRoot)
{}

function NAME() external pure override returns (string memory) {
return 'PerAddressTrancheVestingMerkle';
}

function VERSION() external pure override returns (uint256) {
return 4;
}

function initializeDistributionRecord(
uint256 index, // the beneficiary's index in the merkle root
address beneficiary, // the address that will receive tokens
uint256 amount, // the total claimable by this beneficiary
Tranche[] calldata tranches, // the tranches for the beneficiary (users can have different vesting schedules)
bytes32[] calldata merkleProof
)
external
validMerkleProof(keccak256(abi.encodePacked(index, beneficiary, amount, abi.encode(tranches))), merkleProof)
{
_initializeDistributionRecord(beneficiary, amount);
}

function claim(
uint256 index, // the beneficiary's index in the merkle root
address beneficiary, // the address that will receive tokens
uint256 totalAmount, // the total claimable by this beneficiary
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tranche params

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment

// TODO: should we be providing the tranches already abi encoded to save gas?
Tranche[] calldata tranches, // the tranches for the beneficiary (users can have different vesting schedules)
bytes32[] calldata merkleProof
)
external
validMerkleProof(keccak256(abi.encodePacked(index, beneficiary, totalAmount, abi.encode(tranches))), merkleProof)
nonReentrant
{
bytes memory data = abi.encode(tranches);
// effects
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount, data);
// interactions
_settleClaim(beneficiary, claimedAmount);
}

function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner {
_setMerkleRoot(_merkleRoot);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ contract PriceTierVestingMerkle is PriceTierVesting, MerkleSet {
nonReentrant
{
// effects
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount);
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount, new bytes(0));
// interactions
_settleClaim(beneficiary, claimedAmount);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/hardhat/contracts/claim/PriceTierVestingSale_2_0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ contract PriceTierVestingSale_2_0 is PriceTierVesting {
uint256 totalClaimableAmount = getTotalClaimableAmount(beneficiary);

// effects
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount);
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount, new bytes(0));

// interactions
super._settleClaim(beneficiary, claimedAmount);
Expand All @@ -119,12 +119,12 @@ contract PriceTierVestingSale_2_0 is PriceTierVesting {
}

// get the number of tokens currently claimable by a specific user
function getClaimableAmount(address beneficiary) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary);
function getClaimableAmount(address beneficiary, bytes memory data) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary, data);

// we can get the claimable amount prior to initialization
return
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp)) /
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp, new bytes(0))) /
fractionDenominator;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/hardhat/contracts/claim/TrancheVestingMerkle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract TrancheVestingMerkle is TrancheVesting, MerkleSet {
nonReentrant
{
// effects
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount);
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount, new bytes(0));
// interactions
_settleClaim(beneficiary, claimedAmount);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/hardhat/contracts/claim/TrancheVestingSale_1_3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ contract TrancheVestingSale_1_3 is TrancheVesting {
uint256 totalClaimableAmount = getTotalClaimableAmount(beneficiary);

// effects
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount);
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount, new bytes(0));

// interactions
super._settleClaim(beneficiary, claimedAmount);
Expand All @@ -111,12 +111,12 @@ contract TrancheVestingSale_1_3 is TrancheVesting {
}

// get the number of tokens currently claimable by a specific user
function getClaimableAmount(address beneficiary) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary);
function getClaimableAmount(address beneficiary, bytes memory data) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary, data);

// we can get the claimable amount prior to initialization
return
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp)) /
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp, new bytes(0))) /
fractionDenominator;
}

Expand Down
8 changes: 4 additions & 4 deletions packages/hardhat/contracts/claim/TrancheVestingSale_2_0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ contract TrancheVestingSale_2_0 is TrancheVesting {
uint256 totalClaimableAmount = getTotalClaimableAmount(beneficiary);

// effects
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount);
uint256 claimedAmount = super._executeClaim(beneficiary, totalClaimableAmount, new bytes(0));

// interactions
_settleClaim(beneficiary, claimedAmount);
Expand All @@ -109,12 +109,12 @@ contract TrancheVestingSale_2_0 is TrancheVesting {
}

// get the number of tokens currently claimable by a specific user
function getClaimableAmount(address beneficiary) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary);
function getClaimableAmount(address beneficiary, bytes memory data) public view override returns (uint256) {
if (records[beneficiary].initialized) return super.getClaimableAmount(beneficiary, data);

// we can get the claimable amount prior to initialization
return
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp)) /
(getPurchasedAmount(beneficiary) * getVestedFraction(beneficiary, block.timestamp, new bytes(0))) /
fractionDenominator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ abstract contract AdvancedDistributor is

function _executeClaim(
address beneficiary,
uint256 totalAmount
uint256 totalAmount,
bytes memory data
) internal virtual override returns (uint256 _claimed) {
_claimed = super._executeClaim(beneficiary, totalAmount);
_claimed = super._executeClaim(beneficiary, totalAmount, data);
_reconcileVotingPower(beneficiary);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ abstract contract ContinuousVesting is AdvancedDistributor, IContinuousVesting {

function getVestedFraction(
address beneficiary,
uint256 time // time is in seconds past the epoch (e.g. block.timestamp)
uint256 time, // time is in seconds past the epoch (e.g. block.timestamp)
bytes memory /*data*/
) public view override returns (uint256) {
uint256 delayedTime = time- getFairDelayTime(beneficiary);
// no tokens are vested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ abstract contract CrosschainMerkleDistributor is CrosschainDistributor, MerkleSe
_verifyMembership(_getLeaf(beneficiary, totalAmount, beneficiaryDomain), proof);

// effects
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount);
uint256 claimedAmount = _executeClaim(beneficiary, totalAmount, new bytes(0));

// interactions
// NOTE: xReceive is *NOT* payable (Connext does not handle native assets).
Expand All @@ -100,7 +100,7 @@ abstract contract CrosschainMerkleDistributor is CrosschainDistributor, MerkleSe
) external payable {
_verifyMembership(_getLeaf(_beneficiary, _total, domain), _proof);
// effects
uint256 claimedAmount = _executeClaim(_beneficiary, _total);
uint256 claimedAmount = _executeClaim(_beneficiary, _total, new bytes(0));

// interactions
_settleClaim(_beneficiary, _beneficiary, domain, claimedAmount);
Expand Down Expand Up @@ -137,7 +137,7 @@ abstract contract CrosschainMerkleDistributor is CrosschainDistributor, MerkleSe

// Validate the claim
_verifyMembership(_getLeaf(_beneficiary, _total, _beneficiaryDomain), _proof);
uint256 claimedAmount = _executeClaim(_beneficiary, _total);
uint256 claimedAmount = _executeClaim(_beneficiary, _total, new bytes(0));

_settleClaim(_beneficiary, _recipient, _recipientDomain, claimedAmount);
}
Expand Down
Loading