Skip to content
Merged
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
1 change: 1 addition & 0 deletions interface/IEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface IEscrow {
event TokenRemovedFromWhitelist(address indexed token);
event BatchDeposited (uint indexed batchId, uint repoId, uint timestamp, uint[] depositIds);
event SignerSet (address indexed newSigner);
event BatchDepositLimitSet (uint newLimit);

/**
* @notice Deposits tokens into the escrow on behalf of a specified sender and recipient.
Expand Down
66 changes: 34 additions & 32 deletions libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,38 @@
pragma solidity =0.8.26;

library Errors {
string internal constant NOT_OWNER = "Not Owner";
string internal constant NOT_SUPPORTED = "Not Supported";
string internal constant ALREADY_INITIALIZED = "Already Initialized";
string internal constant LENGTH_MISMATCH = "Length Mismatch";
string internal constant ZERO_SHARE = "Zero Share";
string internal constant NO_TIME_ELAPSED = "No Time Elapsed";
string internal constant NO_NEW_MINTED_SHARES = "No New Minted Shares";
string internal constant NO_PULL_REQUESTS = "No Pull Requests";
string internal constant NO_WEIGHTS = "No Weights";
string internal constant NOT_INITIALIZED = "Not Initialized";
string internal constant NOT_ACCOUNT_OWNER = "Not Account Owner";
string internal constant ALREADY_CLAIMED = "Already Claimed";
string internal constant INVALID_PROOF = "Invalid Proof";
string internal constant INVALID_ROOT = "Invalid Root";
string internal constant NO_CONTRIBUTORS = "No Contributors";
string internal constant TOO_MANY_CONTRIBUTORS = "Too Many Contributors";
string internal constant TOO_MANY_PULL_REQUESTS = "Too Many Pull Requests";
string internal constant NO_PAYMENT_PERMISSION = "No Payment Permission";
string internal constant CLAIM_EXPIRED = "Claim Expired";
string internal constant STILL_CLAIMABLE = "Still Claimable";
string internal constant INVALID_SIGNATURE = "Invalid Signature";
string internal constant INVALID_ADDRESS = "Invalid Address";
string internal constant INVALID_AMOUNT = "Invalid Amount";
string internal constant INVALID_CLAIM_PERIOD = "Invalid Claim Period";
string internal constant INVALID_RECIPIENT = "Invalid Recipient";
string internal constant TOKEN_NOT_WHITELISTED = "Token Not Whitelisted";
string internal constant TOKEN_ALREADY_WHITELISTED = "Token Already Whitelisted";
string internal constant SIGNATURE_EXPIRED = "Signature Expired";
string internal constant INVALID_DEPOSIT_ID = "Invalid Deposit ID";
string internal constant INVALID_TOKEN = "Invalid Token";
string internal constant INVALID_FEE = "Invalid Fee";
string internal constant INVALID_AMOUNT_AFTER_FEE = "Invalid Amount After Fee";
string internal constant NOT_OWNER = "Not Owner";
string internal constant NOT_SUPPORTED = "Not Supported";
string internal constant ALREADY_INITIALIZED = "Already Initialized";
string internal constant LENGTH_MISMATCH = "Length Mismatch";
string internal constant ZERO_SHARE = "Zero Share";
string internal constant NO_TIME_ELAPSED = "No Time Elapsed";
string internal constant NO_NEW_MINTED_SHARES = "No New Minted Shares";
string internal constant NO_PULL_REQUESTS = "No Pull Requests";
string internal constant NO_WEIGHTS = "No Weights";
string internal constant NOT_INITIALIZED = "Not Initialized";
string internal constant NOT_ACCOUNT_OWNER = "Not Account Owner";
string internal constant ALREADY_CLAIMED = "Already Claimed";
string internal constant INVALID_PROOF = "Invalid Proof";
string internal constant INVALID_ROOT = "Invalid Root";
string internal constant NO_CONTRIBUTORS = "No Contributors";
string internal constant TOO_MANY_CONTRIBUTORS = "Too Many Contributors";
string internal constant TOO_MANY_PULL_REQUESTS = "Too Many Pull Requests";
string internal constant NO_PAYMENT_PERMISSION = "No Payment Permission";
string internal constant CLAIM_EXPIRED = "Claim Expired";
string internal constant STILL_CLAIMABLE = "Still Claimable";
string internal constant INVALID_SIGNATURE = "Invalid Signature";
string internal constant INVALID_ADDRESS = "Invalid Address";
string internal constant INVALID_AMOUNT = "Invalid Amount";
string internal constant INVALID_CLAIM_PERIOD = "Invalid Claim Period";
string internal constant INVALID_RECIPIENT = "Invalid Recipient";
string internal constant TOKEN_NOT_WHITELISTED = "Token Not Whitelisted";
string internal constant TOKEN_ALREADY_WHITELISTED = "Token Already Whitelisted";
string internal constant SIGNATURE_EXPIRED = "Signature Expired";
string internal constant INVALID_DEPOSIT_ID = "Invalid Deposit ID";
string internal constant INVALID_TOKEN = "Invalid Token";
string internal constant INVALID_FEE = "Invalid Fee";
string internal constant INVALID_AMOUNT_AFTER_FEE = "Invalid Amount After Fee";
string internal constant INVALID_BATCH_DEPOSIT_LIMIT = "Invalid Batch Deposit Limit";
string internal constant BATCH_DEPOSIT_LIMIT_EXCEEDED = "Batch Deposit Limit Exceeded";
}
2 changes: 2 additions & 0 deletions libraries/Params.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ library Params {
address constant OWNER = 0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F;
address constant SIGNER = 0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F;

uint constant BATCH_DEPOSIT_LIMIT = 500;

// BASE
address constant BASE_WETH = 0x4200000000000000000000000000000000000006;
address constant BASE_USDC = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913;
Expand Down
8 changes: 7 additions & 1 deletion script/Deploy.Base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ contract DeployBase is Deploy {
address[] memory initialWhitelistedTokens = new address[](1);
initialWhitelistedTokens[0] = Params.BASE_USDC;

escrow = deploy(Params.OWNER, Params.SIGNER, initialWhitelistedTokens, Params.BASE_FEE_BPS);
escrow = deploy(
Params.OWNER,
Params.SIGNER,
initialWhitelistedTokens,
Params.BASE_FEE_BPS,
Params.BATCH_DEPOSIT_LIMIT
);
}
}
2 changes: 1 addition & 1 deletion script/Deploy.Test.Base.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ abstract contract DeployTestBase is Deploy {
initialWhitelistedTokens[1] = usdc;
initialWhitelistedTokens[2] = address(mockUSDC);

escrow = deploy(owner, signer, initialWhitelistedTokens, 0);
escrow = deploy(owner, signer, initialWhitelistedTokens, 0, Params.BATCH_DEPOSIT_LIMIT);
}

function createTestPayments(
Expand Down
6 changes: 4 additions & 2 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ contract Deploy is Script {
address owner,
address signer,
address[] memory initialWhitelistedTokens,
uint feeBps
uint feeBps,
uint batchDepositLimit
)
public
returns (Escrow escrow)
Expand All @@ -21,7 +22,8 @@ contract Deploy is Script {
owner,
signer,
initialWhitelistedTokens,
feeBps
feeBps,
batchDepositLimit
);

vm.stopBroadcast();
Expand Down
3 changes: 2 additions & 1 deletion script/utils/CreatePayments.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ contract CreatePayments is Script {
uint constant AMOUNT_PER_DEPOSIT = 100 * 10**6;
address constant ESCROW_ADDRESS = 0x18578b0168D940623b89Dd0Be880fF994305Fd7e;
address constant TOKEN = 0x883066fabE2CC5b8f5dC626bF2eb47C6FBD4BE03;
uint constant REPO_ID = 1234;

function run() public {
deploy(
Expand Down Expand Up @@ -53,7 +54,7 @@ contract CreatePayments is Script {

mockUSDC.mint(sender, amountPerDeposit * numberOfDeposits);
mockUSDC.approve(address(escrow), amountPerDeposit * numberOfDeposits);
escrow.batchDeposit(depositParams, numberOfDeposits, block.timestamp);
escrow.batchDeposit(depositParams, REPO_ID, block.timestamp);

vm.stopBroadcast();

Expand Down
2 changes: 1 addition & 1 deletion script/utils/Gas.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract DeploySepolia is Script {
address[] memory initialWhitelistedTokens = new address[](1);
initialWhitelistedTokens[0] = address(mockUSDC);

Escrow escrow = new Deploy().deploy(Params.OWNER, Params.SIGNER, initialWhitelistedTokens, 0);
Escrow escrow = new Deploy().deploy(Params.OWNER, Params.SIGNER, initialWhitelistedTokens, 0, Params.BATCH_DEPOSIT_LIMIT);

for (uint256 j = 0; j < NUM_DEPOSITS.length; j++) {
uint256 numDeposits = NUM_DEPOSITS[j];
Expand Down
64 changes: 34 additions & 30 deletions src/Escrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,22 @@ contract Escrow is Owned, IEscrow {
uint public batchCount;
uint public protocolFeeBps;
address public feeRecipient;
uint public batchDepositLimit;

constructor(
address _owner,
address _signer,
address[] memory _initialWhitelistedTokens,
uint _initialFeeBps
uint _initialFeeBps,
uint _initialBatchDepositLimit
) Owned(_owner) {
require(_initialFeeBps <= MAX_FEE_BPS, Errors.INVALID_FEE);
feeRecipient = _owner;
protocolFeeBps = _initialFeeBps;
CLAIM_INITIAL_CHAIN_ID = block.chainid;
CLAIM_INITIAL_DOMAIN_SEPARATOR = _computeClaimDomainSeparator();
signer = _signer;
batchDepositLimit = _initialBatchDepositLimit;

for (uint256 i = 0; i < _initialWhitelistedTokens.length; i++) {
_whitelistedTokens.add(_initialWhitelistedTokens[i]);
Expand Down Expand Up @@ -129,6 +132,7 @@ contract Escrow is Owned, IEscrow {
external
returns (uint[] memory depositIds)
{
require(params.length <= batchDepositLimit, Errors.BATCH_DEPOSIT_LIMIT_EXCEEDED);
depositIds = new uint[](params.length);

for (uint256 i = 0; i < params.length; i++) {
Expand Down Expand Up @@ -274,7 +278,7 @@ contract Escrow is Owned, IEscrow {
}

/*//////////////////////////////////////////////////////////////
WHITELIST
OWNER OPERATIONS
//////////////////////////////////////////////////////////////*/
function addWhitelistedToken(address token) external onlyOwner {
require(token != address(0), Errors.INVALID_ADDRESS);
Expand All @@ -291,31 +295,6 @@ contract Escrow is Owned, IEscrow {
return _whitelistedTokens.contains(token);
}

function getWhitelistedTokens() external view returns (address[] memory) {
uint256 length = _whitelistedTokens.length();
address[] memory tokens = new address[](length);

for (uint256 i = 0; i < length; i++) {
tokens[i] = _whitelistedTokens.at(i);
}

return tokens;
}

/*//////////////////////////////////////////////////////////////
GETTERS
//////////////////////////////////////////////////////////////*/
function getDepositsBySender(address sender) external view returns (uint[] memory) {
return senderDeposits[sender];
}

function getDepositsByRecipient(address recipient) external view returns (uint[] memory) {
return recipientDeposits[recipient];
}

/*//////////////////////////////////////////////////////////////
FEE MANAGEMENT (Owner Only)
//////////////////////////////////////////////////////////////*/
function setProtocolFeeBps(uint _newFeeBps) external onlyOwner {
require(_newFeeBps <= MAX_FEE_BPS, Errors.INVALID_FEE);
protocolFeeBps = _newFeeBps;
Expand All @@ -328,12 +307,37 @@ contract Escrow is Owned, IEscrow {
emit FeeRecipientSet(_newFeeRecipient);
}

/*//////////////////////////////////////////////////////////////
SIGNER MANAGEMENT (Owner Only)
//////////////////////////////////////////////////////////////*/
function setSigner(address _newSigner) external onlyOwner {
require(_newSigner != address(0), Errors.INVALID_ADDRESS);
signer = _newSigner;
emit SignerSet(_newSigner);
}

function setBatchDepositLimit(uint _newLimit) external onlyOwner {
require(_newLimit > 0, Errors.INVALID_BATCH_DEPOSIT_LIMIT);
batchDepositLimit = _newLimit;
emit BatchDepositLimitSet(_newLimit);
}

/*//////////////////////////////////////////////////////////////
GETTERS
//////////////////////////////////////////////////////////////*/
function getDepositsBySender(address sender) external view returns (uint[] memory) {
return senderDeposits[sender];
}

function getDepositsByRecipient(address recipient) external view returns (uint[] memory) {
return recipientDeposits[recipient];
}

function getWhitelistedTokens() external view returns (address[] memory) {
uint256 length = _whitelistedTokens.length();
address[] memory tokens = new address[](length);

for (uint256 i = 0; i < length; i++) {
tokens[i] = _whitelistedTokens.at(i);
}

return tokens;
}
}
14 changes: 8 additions & 6 deletions test/Deploy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ contract Deploy_Test is Test {
function test_deploy() public {
Escrow escrow = deployer.run();

assertTrue(address(escrow) != address(0), "Escrow not deployed");
assertTrue(escrow.isTokenWhitelisted(Params.BASE_USDC), "WETH not whitelisted");
assertEq (escrow.owner(), Params.OWNER, "Incorrect owner");
assertEq (escrow.signer(), Params.SIGNER, "Incorrect signer");
assertEq (escrow.feeRecipient(), Params.OWNER, "Incorrect fee recipient");
assertEq (escrow.protocolFeeBps(), Params.BASE_FEE_BPS, "Incorrect fee");
assertTrue(address(escrow) != address(0), "Escrow not deployed");
assertTrue(escrow.isTokenWhitelisted(Params.BASE_USDC), "WETH not whitelisted");

assertEq (escrow.owner(), Params.OWNER, "Incorrect owner");
assertEq (escrow.signer(), Params.SIGNER, "Incorrect signer");
assertEq (escrow.feeRecipient(), Params.OWNER, "Incorrect fee recipient");
assertEq (escrow.protocolFeeBps(), Params.BASE_FEE_BPS, "Incorrect fee");
assertEq (escrow.batchDepositLimit(), Params.BATCH_DEPOSIT_LIMIT, "Incorrect batch deposit limit");
}
}
3 changes: 2 additions & 1 deletion test/Escrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {Escrow} from "../src/Escrow.sol";
import {DepositParams} from "../interface/IEscrow.sol";
import {Deploy} from "../script/Deploy.s.sol";
import {Errors} from "../libraries/Errors.sol";
import {Params} from "../libraries/Params.sol";

contract Base_Test is Test {

Expand All @@ -26,7 +27,7 @@ contract Base_Test is Test {
function setUp() public {
address[] memory initialWhitelistedTokens = new address[](1);
initialWhitelistedTokens[0] = address(wETH);
escrow = new Deploy().deploy(owner, owner, initialWhitelistedTokens, 0);
escrow = new Deploy().deploy(owner, owner, initialWhitelistedTokens, 0, Params.BATCH_DEPOSIT_LIMIT);

alice = makeAddr("alice");
bob = makeAddr("bob");
Expand Down
2 changes: 1 addition & 1 deletion test/EscrowWithFee.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract Base_Test is Test {
function setUp() public {
address[] memory initialWhitelistedTokens = new address[](1);
initialWhitelistedTokens[0] = address(wETH);
escrow = new Deploy().deploy(owner, owner, initialWhitelistedTokens, Params.BASE_FEE_BPS);
escrow = new Deploy().deploy(owner, owner, initialWhitelistedTokens, Params.BASE_FEE_BPS, Params.BATCH_DEPOSIT_LIMIT);

alice = makeAddr("alice");
bob = makeAddr("bob");
Expand Down
Loading