Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/centrifuge/connectors into …
Browse files Browse the repository at this point in the history
…deterministic-deploys
  • Loading branch information
hieronx committed Apr 27, 2023
2 parents 8cb16ad + c1fc9c1 commit 603e628
Show file tree
Hide file tree
Showing 10 changed files with 968 additions and 538 deletions.
168 changes: 123 additions & 45 deletions src/Connector.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,29 @@ interface GatewayLike {
function transferTrancheTokensToCentrifuge(
uint64 poolId,
bytes16 trancheId,
address sender,
bytes32 destinationAddress,
uint128 amount
) external;
function transferTrancheTokensToEVM(
uint64 poolId,
bytes16 trancheId,
uint256 destinationChainId,
address sender,
uint64 destinationChainId,
address destinationAddress,
uint128 amount
) external;
function transfer(uint128 currency, address sender, bytes32 recipient, uint128 amount) external;
function increaseInvestOrder(uint64 poolId, bytes16 trancheId, address investor, uint128 currency, uint128 amount)
external;
function decreaseInvestOrder(uint64 poolId, bytes16 trancheId, address investor, uint128 currency, uint128 amount)
external;
function increaseRedeemOrder(uint64 poolId, bytes16 trancheId, address investor, uint128 currency, uint128 amount)
external;
function decreaseRedeemOrder(uint64 poolId, bytes16 trancheId, address investor, uint128 currency, uint128 amount)
external;
function collectInvest(uint64 poolId, bytes16 trancheId, address investor) external;
function collectRedeem(uint64 poolId, bytes16 trancheId, address investor) external;
}

interface EscrowLike {
Expand All @@ -29,7 +42,6 @@ interface EscrowLike {
struct Pool {
uint64 poolId;
uint256 createdAt;
address currency;
}

struct Tranche {
Expand All @@ -40,15 +52,22 @@ struct Tranche {
// This leads to duplicate storage (also in the ERC20 contract), ideally we should refactor this somehow
string tokenName;
string tokenSymbol;
uint8 decimals;
}

contract CentrifugeConnector {
mapping(address => uint256) public wards;
mapping(uint64 => Pool) public pools;
mapping(uint64 => mapping(bytes16 => Tranche)) public tranches;

mapping(uint128 => address) public currencyIdToAddress;
// The reverse mapping of `currencyIdToAddress`
mapping(address => uint128) public currencyAddressToId;

mapping(uint64 => mapping(address => bool)) public allowedPoolCurrencies;

GatewayLike public gateway;
EscrowLike public escrow;
EscrowLike public immutable escrow;

TrancheTokenFactoryLike public immutable tokenFactory;
MemberlistFactoryLike public immutable memberlistFactory;
Expand All @@ -57,7 +76,9 @@ contract CentrifugeConnector {
event Rely(address indexed user);
event Deny(address indexed user);
event File(bytes32 indexed what, address data);
event CurrencyAdded(uint128 indexed currency, address indexed currencyAddress);
event PoolAdded(uint256 indexed poolId);
event PoolCurrencyAllowed(uint128 currency, uint64 poolId);
event TrancheAdded(uint256 indexed poolId, bytes16 indexed trancheId);
event TrancheDeployed(uint256 indexed poolId, bytes16 indexed trancheId, address indexed token);

Expand Down Expand Up @@ -98,6 +119,17 @@ contract CentrifugeConnector {
}

// --- Outgoing message handling ---
function transfer(address currencyAddress, bytes32 recipient, uint128 amount) public {
uint128 currency = currencyAddressToId[currencyAddress];
require(currency != 0, "CentrifugeConnector/unknown-currency");

ERC20Like erc20 = ERC20Like(currencyAddress);
require(erc20.balanceOf(msg.sender) >= amount, "CentrifugeConnector/insufficient-balance");
require(erc20.transferFrom(msg.sender, address(escrow), amount), "CentrifugeConnector/currency-transfer-failed");

gateway.transfer(currency, msg.sender, recipient, amount);
}

function transferTrancheTokensToCentrifuge(
uint64 poolId,
bytes16 trancheId,
Expand All @@ -110,13 +142,13 @@ contract CentrifugeConnector {
require(token.balanceOf(msg.sender) >= amount, "CentrifugeConnector/insufficient-balance");
token.burn(msg.sender, amount);

gateway.transferTrancheTokensToCentrifuge(poolId, trancheId, destinationAddress, amount);
gateway.transferTrancheTokensToCentrifuge(poolId, trancheId, msg.sender, destinationAddress, amount);
}

function transferTrancheTokensToEVM(
uint64 poolId,
bytes16 trancheId,
uint256 destinationChainId,
uint64 destinationChainId,
address destinationAddress,
uint128 amount
) public {
Expand All @@ -126,75 +158,115 @@ contract CentrifugeConnector {
require(token.balanceOf(msg.sender) >= amount, "CentrifugeConnector/insufficient-balance");
token.burn(msg.sender, amount);

gateway.transferTrancheTokensToEVM(poolId, trancheId, destinationChainId, destinationAddress, amount);
gateway.transferTrancheTokensToEVM(
poolId, trancheId, msg.sender, destinationChainId, destinationAddress, amount
);
}

function increaseInvestOrder(uint64 poolId, bytes16 trancheId, uint128 amount) public {
Pool storage pool = pools[poolId];
require(pool.createdAt > 0, "CentrifugeConnector/invalid-pool");

function increaseInvestOrder(uint64 poolId, bytes16 trancheId, address currencyAddress, uint128 amount) public {
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-token");
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

uint128 currency = currencyAddressToId[currencyAddress];
require(currency != 0, "CentrifugeConnector/unknown-currency");
require(allowedPoolCurrencies[poolId][currencyAddress], "CentrifugeConnector/pool-currency-not-allowed");

require(
ERC20Like(pool.currency).transferFrom(msg.sender, address(escrow), amount),
ERC20Like(currencyAddress).transferFrom(msg.sender, address(escrow), amount),
"Centrifuge/Connector/currency-transfer-failed"
);

// TODO: send message to the gateway. Depends on https://github.com/centrifuge/connectors/pull/52
gateway.increaseInvestOrder(poolId, trancheId, msg.sender, currency, amount);
}

function decreaseInvestOrder(uint64 poolId, bytes16 trancheId, uint128 amount) public {
Pool storage pool = pools[poolId];
require(pool.createdAt > 0, "CentrifugeConnector/invalid-pool");

function decreaseInvestOrder(uint64 poolId, bytes16 trancheId, address currencyAddress, uint128 amount) public {
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-token");
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

// TODO: send message to the gateway. Depends on https://github.com/centrifuge/connectors/pull/52
}
uint128 currency = currencyAddressToId[currencyAddress];
require(currency != 0, "CentrifugeConnector/unknown-currency");
require(allowedPoolCurrencies[poolId][currencyAddress], "CentrifugeConnector/pool-currency-not-allowed");

function increaseRedeemOrder(uint64 poolId, bytes16 trancheId, uint128 amount) public {
// TODO(nuno)
gateway.decreaseInvestOrder(poolId, trancheId, msg.sender, currency, amount);
}

function decreaseRedeemOrder(uint64 poolId, bytes16 trancheId, uint128 amount) public {
// TODO(nuno)
}
function increaseRedeemOrder(uint64 poolId, bytes16 trancheId, address currencyAddress, uint128 amount) public {
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

function collectRedeem(uint64 poolId, bytes16 trancheId) public {
// TODO(nuno)
uint128 currency = currencyAddressToId[currencyAddress];
require(currency != 0, "CentrifugeConnector/unknown-currency");
require(allowedPoolCurrencies[poolId][currencyAddress], "CentrifugeConnector/pool-currency-not-allowed");

gateway.increaseRedeemOrder(poolId, trancheId, msg.sender, currency, amount);
}

function collectForRedeem(uint64 poolId, bytes16 trancheId, bytes32 userAddress) public {
// TODO(nuno)
function decreaseRedeemOrder(uint64 poolId, bytes16 trancheId, address currencyAddress, uint128 amount) public {
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

uint128 currency = currencyAddressToId[currencyAddress];
require(currency != 0, "CentrifugeConnector/unknown-currency");
require(allowedPoolCurrencies[poolId][currencyAddress], "CentrifugeConnector/pool-currency-not-allowed");

gateway.decreaseRedeemOrder(poolId, trancheId, msg.sender, currency, amount);
}

function collectInvest(uint64 poolId, bytes16 trancheId) public {
// TODO(nuno)
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

gateway.collectInvest(poolId, trancheId, address(msg.sender));
}

function collectForInvest(uint64 poolId, bytes16 trancheId, bytes32 userAddress) public {
// TODO(nuno)
function collectRedeem(uint64 poolId, bytes16 trancheId) public {
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-tranche-token");
require(token.hasMember(msg.sender), "CentrifugeConnector/not-a-member");

gateway.collectRedeem(poolId, trancheId, address(msg.sender));
}

// --- Incoming message handling ---
// todo(nuno): store currency and decimals
function addPool(uint64 poolId, uint128 currency, uint8 decimals) public onlyGateway {
function addCurrency(uint128 currency, address currencyAddress) public onlyGateway {
require(currencyIdToAddress[currency] == address(0), "CentrifugeConnector/currency-id-in-use");
require(currencyAddressToId[currencyAddress] == 0, "CentrifugeConnector/currency-address-in-use");

currencyIdToAddress[currency] = currencyAddress;
currencyAddressToId[currencyAddress] = currency;
emit CurrencyAdded(currency, currencyAddress);
}

function addPool(uint64 poolId) public onlyGateway {
Pool storage pool = pools[poolId];
require(pool.createdAt == 0, "CentrifugeConnector/pool-already-added");
pool.poolId = poolId;
pool.createdAt = block.timestamp;
emit PoolAdded(poolId);
}

function allowPoolCurrency(uint64 poolId, uint128 currency) public onlyGateway {
Pool storage pool = pools[poolId];
require(pool.createdAt > 0, "CentrifugeConnector/invalid-pool");

address currencyAddress = currencyIdToAddress[currency];
require(currencyAddress != address(0), "CentrifugeConnector/unknown-currency");

allowedPoolCurrencies[poolId][currencyAddress] = true;
emit PoolCurrencyAllowed(currency, poolId);
}

function addTranche(
uint64 poolId,
bytes16 trancheId,
string memory tokenName,
string memory tokenSymbol,
uint8 decimals,
uint128 price
) public onlyGateway {
Pool storage pool = pools[poolId];
Expand All @@ -206,6 +278,7 @@ contract CentrifugeConnector {
tranche.lastPriceUpdate = block.timestamp;
tranche.tokenName = tokenName;
tranche.tokenSymbol = tokenSymbol;
tranche.decimals = decimals;

emit TrancheAdded(poolId, trancheId);
}
Expand All @@ -215,10 +288,8 @@ contract CentrifugeConnector {
require(tranche.lastPriceUpdate > 0, "CentrifugeConnector/invalid-pool-or-tranche");
require(tranche.token == address(0), "CentrifugeConnector/tranche-already-deployed");

// TODO: use actual decimals
uint8 decimals = 18;
address token =
tokenFactory.newTrancheToken(poolId, trancheId, tranche.tokenName, tranche.tokenSymbol, decimals);
tokenFactory.newTrancheToken(poolId, trancheId, tranche.tokenName, tranche.tokenSymbol, tranche.decimals);
tranche.token = token;

address memberlist = memberlistFactory.newMemberlist();
Expand All @@ -242,14 +313,21 @@ contract CentrifugeConnector {
memberlist.updateMember(user, validUntil);
}

function handleTransferTrancheTokens(
uint64 poolId,
bytes16 trancheId,
uint256 destinationChainId,
address destinationAddress,
uint128 amount
) public onlyGateway {
require(destinationChainId == block.chainid, "CentrifugeConnector/invalid-chain-id");
function handleTransfer(uint128 currency, address recipient, uint128 amount) public onlyGateway {
address currencyAddress = currencyIdToAddress[currency];
require(currencyAddress != address(0), "CentrifugeConnector/unknown-currency");

EscrowLike(escrow).approve(currencyAddress, address(this), amount);
require(
ERC20Like(currencyAddress).transferFrom(address(escrow), recipient, amount),
"CentrifugeConnector/currency-transfer-failed"
);
}

function handleTransferTrancheTokens(uint64 poolId, bytes16 trancheId, address destinationAddress, uint128 amount)
public
onlyGateway
{
RestrictedTokenLike token = RestrictedTokenLike(tranches[poolId][trancheId].token);
require(address(token) != address(0), "CentrifugeConnector/unknown-token");

Expand Down
Loading

0 comments on commit 603e628

Please sign in to comment.