Smart Contract Integrations
Integrate syrupUSD (syrupUSDC / syrupUSDT) via smart contracts. Lenders (your smart contracts) must deposit through SyrupRouter with authorization handled by PoolPermissionManager.
Overview
1. Syrup Protocol Overview
Smart contracts integrating with syrupUSD act as lenders and must interact via SyrupRouter
. Authorization is enforced by PoolPermissionManager
. First-time deposits require an authorization signature; subsequent deposits can call deposit
directly once authorized.
2. Syrup Addresses
All ABIs are available on GitHub: Maple JS (ABIs)
Syrup USDC
SyrupRouter
WithdrawalManagerQueue
Syrup USDT
SyrupRouter
WithdrawalManagerQueue
Shared (Global)
PoolPermissionManager
3. Testing on Sepolia
Contact [email protected] for test USDC/USDT
and access. See the Sepolia tab above for addresses.
Deposit
1. Determine Lender Authorization (onchain)
Use PoolPermissionManager
to verify lender authorization for a specific pool. You can derive the manager onchain from the Pool.
interface IPool { function manager() external view returns (address); }
interface IPoolManager { function poolPermissionManager() external view returns (address); }
interface IPoolPermissionManager {
function lenderBitmaps(address lender) external view returns (uint256);
function poolBitmaps(address pool) external view returns (uint256);
}
function getPoolPermissionManager(address pool) internal view returns (address) {
address manager = IPool(pool).manager();
return IPoolManager(manager).poolPermissionManager();
}
function isAuthorized(address pool, address lender) internal view returns (bool) {
address ppm = getPoolPermissionManager(pool);
uint256 lenderBitmap = IPoolPermissionManager(ppm).lenderBitmaps(lender);
uint256 poolBitmap = IPoolPermissionManager(ppm).poolBitmaps(pool);
// Authorized if XOR equals the pool bitmap
return (lenderBitmap ^ poolBitmap) == poolBitmap;
}
Mainnet PoolPermissionManager
(for reference): 0xBe10aDcE8B6E3E02Db384E7FaDA5395DD113D8b3
2. Retrieve Authorization Signature
If not authorized, contact [email protected] to obtain:
bitmap
,deadline
,v
,r
,s
depositData
(provided by Maple). Conventionally"0:<integrator-name>"
, encoded asbytes32
. Keep within 32 bytes when hex-encoded.
3. Execute the Deposit
Minimal SC calls (lender must hold sufficient USDC/USDT):
interface IERC20 { function approve(address spender, uint256 amount) external returns (bool); }
interface ISyrupRouter {
function deposit(uint256 amount, bytes32 depositData) external returns (uint256 shares);
function authorizeAndDeposit(
uint256 bitmap,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s,
uint256 amount,
bytes32 depositData
) external returns (uint256 shares);
}
function depositAuthorized(
address asset,
address router,
uint256 amount,
bytes32 depositData
) external {
IERC20(asset).approve(router, amount);
ISyrupRouter(router).deposit(amount, depositData);
}
function authorizeAndDeposit(
address asset,
address router,
uint256 amount,
bytes32 depositData,
uint256 bitmap,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
IERC20(asset).approve(router, amount);
ISyrupRouter(router).authorizeAndDeposit(bitmap, deadline, v, r, s, amount, depositData);
}
Withdraw
1. Retrieve Lender’s Balance
interface IPool {
function balanceOf(address account) external view returns (uint256);
function convertToExitAssets(uint256 shares) external view returns (uint256);
}
function getLenderPosition(address pool, address lender) external view returns (uint256 shares, uint256 exitAssets) {
shares = IPool(pool).balanceOf(lender);
exitAssets = IPool(pool).convertToExitAssets(shares);
}
2. Calculate Shares to Redeem
Use full balance for full redemption, or compute shares for a specific asset amount.
interface IPool { function convertToExitShares(uint256 assets) external view returns (uint256); }
function sharesForAssets(address pool, uint256 assetAmount) external view returns (uint256) {
return IPool(pool).convertToExitShares(assetAmount);
}
3. Execute the Withdrawal
Submit a withdrawal request to the pool.
interface IPool { function requestRedeem(uint256 shares, address receiver) external returns (uint256); }
function requestWithdrawal(address pool, uint256 shares, address receiver) external {
IPool(pool).requestRedeem(shares, receiver);
}
Withdrawals are processed automatically by Maple. If there is sufficient liquidity in the pool, the withdrawal will be processed within a few minutes. Expected processing time is typically less than 2 days, but it can take up to 30 days depending on available liquidity.
Edge Cases
Not authorized → use
authorizeAndDeposit
with signatureInsufficient allowance → call
approve(router, amount)
before depositing
FAQ
Last updated