Smart Contract Integration

Connect to the RAY smart contracts directly on the Ethereum blockchain.

Documentation on how to integrate with RAY smart contracts directly on the Ethereum blockchain.

To start, check out Installation of RAY and Testing of RAY.

See a full example of a smart contract that integrates with RAY here. Then see an example of how to test that smart contract integration with RAY here.

Table of Contents

Smart Contracts

RAY provides a simple interface for developers to hook into. For depositing and withdrawing assets call PortfolioManager.sol. For calculating the value of an existing position call NAVCalculator.sol.

The interface RAY.sol contains all relevant function signatures.

Smart Contracts

ABI

Mainnet Address

PortfolioManager.sol

JSON

0x06a5Bf70BfF314177488864Fe03576ff608e6aec

NAVCalculator.sol

JSON

0xD23fA5F1a001eCDed63b45Da426972fB2AAD2760

RAYToken.sol

JSON

0xE215e8160a5e0A03f2D6c7900b050F2f04eA5Cbb

Customize Your Portfolio

RAY allows you to choose which asset you'd like to supply and which Opportunities to rebalance between. Each specific combination of the asset and Opportunities have a portfolio identifier represented as a bytes32 value. You will need this identifier when making calls to the smart contract interface.

To dynamically generate these, the template used is as follows:

keccak256( {CamelCase Coin Type Ticker} + {CamelCase Opportunities in Alphabetical Order} ); Example: The result ofkeccak256(EthCompoundDydx) is the portfolio id of a RAY that rebalances ETH between Compound and dY/dX.

0x needs to be pre-pended to the result, some keccak256() generators don't automatically add it.

Below are some example values.

Opportunities: Compound, dY/dX, bZx

Assets

  • ETH: 0xbe72e724d4b9326428f7faca782d2dcc9e3e10824e8cf48a6499f23d695fd018

  • DAI: 0x87e3990b15e1e64e3a17b0e4ebfcc4c03cc5ec64a33b442ae01ef15d9dadb575

  • USDC: 0x7c80b0e3ce0d2cabe1a3dfc888fca469bab09beccc3496f88cba8613d159a65b

There are many possible portfolios, check them out here

Mint A RAY Token

Minting a RAY token creates a new position for the user. The new position is represented as an ERC-721 RAY token and initially has a value equivalent to the parameter value.

PortfolioManager.sol
function mint(bytes32 portfolioId, address beneficiary, uint value) external payable returns (bytes32)
Function Parameters
Return Value

msg.sender: The account that will supply the asset

portfolioId: The corresponding id for the basket of opportunities to associate with this RAY token - see Customize Your Portfolio

beneficiary: The account that will own the RAY token

value: The amount in the smallest units of the asset, to deposit

Unique identifier of the newly minted RAY token

When depositing ERC20 tokens, the funder (msg.sender) must first approve PortfolioManager.solto access their assets for the specified value.

Examples:

Solidity

Mint a RAY by depositing an ERC20
/// Below example mints a RAY token by depositing
/// 100 of an ERC20 token. In this example, the RAY
/// will be owned by this smart contract.
ERC20(TokenAddress).approve(PortfolioManagerAddress, 100); // approve the transfer
bytes32 rayTokenId = RAY(PortfolioManagerAddress).mint(portfolioId, address(this), 100); // mint a RAY token and store the tokenId
Mint a RAY by depositing ETH
/// Below example mints a RAY token by depositing
/// 100 wei of ETH. In this example, the RAY will be
/// owned by this smart contract.
bytes32 rayTokenId = RAY(PortfolioManagerAddress).mint.value(100)(portfolioId, address(this), 100); // mint a RAY token and store the tokenId

Deposit Into Existing RAY Token

Users can add additional value to an existing RAY token through the deposit function.

PortfolioManager.sol
function deposit(bytes32 tokenId, uint value) external payable
Function Parameters

msg.sender: The account that will supply the asset

tokenId: The unique identifier of the RAY token to deposit value into

value: The amount in the smallest units of the asset, to deposit

When depositing ERC20 tokens, the funder (msg.sender) must first approve PortfolioManager.solto access their assets for the specified value.

Examples:

Solidity

Deposit ERC20 tokens to an existing RAY
/// Below example increases a RAY token's capital by
/// depositing 100 of an ERC20 token. The RAY token receiving
/// the deposit is specified by 'rayTokenId'
ERC20(TokenAddress).approve(PortfolioManagerAddress, 100); // approve the transfer
bytes32 rayTokenId = RAY(PortfolioManagerAddress).deposit(rayTokenId, 100);
Deposit ETH to an existing RAY
/// Below example increases a RAY token's capital by
/// depositing 100 wei of ETH. The RAY token receiving
/// the deposit is specified by 'rayTokenId'
bytes32 rayTokenId = RAY(PortfolioManagerAddress).deposit.value(100)(rayTokenId, 100);

Redeem Funds

Redeeming allows a user to partially or fully withdraw the underlying value from their RAY token.

PortfolioManager.sol
function redeem(bytes32 tokenId, uint valueToWithdraw, address originalCaller) external returns(uint)
Function Parameters
Return Value

tokenId: The unique identifier of the RAY token to withdraw value from

valueToWithdraw: The amount in the smallest units of the asset, to withdraw

originalCaller: The msg.sender. (This parameter can be set to anything, only relevant if the msg.sender is our GasFunder.sol smart contract which enables paying gas on user transactions)

The value withdrawn after system fees have been taken

Examples:

Solidity

Redeem a RAY token
/// Below example withdraws 100 of the underlying asset
/// of the RAY token specified by 'rayTokenId'. The
/// total value received back after fees is returned.
uint valueAfterFee = RAY(PortfolioManagerAddress).redeem(rayTokenId, 100, address(this));

Get RAY Token Value

Users can use this function to get the current value of their RAY token.

NAVCalculator.sol
function getTokenValue(bytes32 portfolioId, bytes32 tokenId) public view returns(uint, uint)
Function Parameters
Return Value

portfolioId: The corresponding id for the basket of opportunities associated with this RAY token - see Customize Your Portfolio

tokenId: The unique identifier of the RAY token to get the value of

A two index object: (uint tokenValue, uint pricePerShare)

The first index contains the token's current value in-kind. Ex. If the token's principal type is DAI, the value is represented in the smallest units of DAI.

The second index contains the portfolio's current price per share scaled up by 1e18.

Examples:

Solidity

Get the token value of a RAY
/// Below example gets the value of a RAY token, specificied
/// by 'rayTokenId'
uint tokenValue;
uint pricePerShare;
(tokenValue, pricePerShare) = RAY(NAVCalculatorAddress).getTokenValue(portfolioId, rayTokenId);

Burn A RAY Token

Burning allows a user to trade in their full RAY token for all the underlying value. This is a call to RAYToken.sol which uses the ERC721 standard , where the user transfers their token to PortfolioManager.sol

ERC721.sol
Plain Text
function safeTransferFrom(address from, address to, bytes32 tokenId) external
Function Parameters

from : The address of the owner

to: The contract address of PortfolioManager.sol

tokenId: The unique identifier of the RAY token to transfer

Ensure the to parameter is equivalent to the address ofPortfolioManager.sol

The owner of the RAY token that is burnt will receive the full underlying value.