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
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,76 @@
// 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
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
{
bytes memory data = abi.encode(start, cliff, end);
// 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
@@ -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
// 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
12 changes: 7 additions & 5 deletions packages/hardhat/contracts/claim/abstract/Distributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ abstract contract Distributor is IDistributor, ReentrancyGuard {
*/
function _executeClaim(
address beneficiary,
uint256 _totalAmount
uint256 _totalAmount,
bytes memory data
) internal virtual returns (uint256) {
uint120 totalAmount = uint120(_totalAmount);

Expand All @@ -75,7 +76,7 @@ abstract contract Distributor is IDistributor, ReentrancyGuard {
_initializeDistributionRecord(beneficiary, totalAmount);
}

uint120 claimableAmount = uint120(getClaimableAmount(beneficiary));
uint120 claimableAmount = uint120(getClaimableAmount(beneficiary, data));
require(claimableAmount > 0, 'Distributor: no more tokens claimable right now');

records[beneficiary].claimed += claimableAmount;
Expand Down Expand Up @@ -105,20 +106,21 @@ abstract contract Distributor is IDistributor, ReentrancyGuard {
// Get tokens vested as fraction of fractionDenominator
function getVestedFraction(
address beneficiary,
uint256 time
uint256 time,
bytes memory data
) public view virtual returns (uint256);

function getFractionDenominator() public view returns (uint256) {
return fractionDenominator;
}

// get the number of tokens currently claimable by a specific use
function getClaimableAmount(address beneficiary) public view virtual returns (uint256) {
function getClaimableAmount(address beneficiary, bytes memory data) public view virtual returns (uint256) {
require(records[beneficiary].initialized, 'Distributor: claim not initialized');

DistributionRecord memory record = records[beneficiary];

uint256 claimable = (record.total * getVestedFraction(beneficiary, block.timestamp)) /
uint256 claimable = (record.total * getVestedFraction(beneficiary, block.timestamp, data)) /
fractionDenominator;
return
record.claimed >= claimable
Expand Down
Loading
Loading