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
149 changes: 126 additions & 23 deletions contracts/core/diaspore/DebtEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,26 @@ contract DebtEngine is ERC721Base, Ownable {
bytes _callData
);

// This Token(ERC20) works like the fuel of our engine,
// when lend or pay a debt use this Token
IERC20 public token;

// The array to storage the debs
mapping(bytes32 => Debt) public debts;
// Used in create function, increment every create
mapping(address => uint256) public nonces;

struct Debt {
bool error;
uint128 balance;
Model model;
address creator;
address oracle;
bool error; // Used to mark a debt in ERROR status
uint128 balance; // Balance of the debt
Model model; // Model of the debt
address creator; // The sender of the create, create2, create3 functions
address oracle; // Oracle of the debt, if is address(0) the debt is in Token
// in other case the debt use the oracle to get the rate
}

/**
@notice Set the Token
*/
constructor (
IERC20 _token
) public ERC721Base("RCN Debt Record", "RDR") {
Expand All @@ -105,17 +112,38 @@ contract DebtEngine is ERC721Base, Ownable {
require(address(_token).isContract(), "Token should be a contract");
}

/**
@notice Set provider, look in ERC721Base

@dev Only the owner can use this function
*/
function setURIProvider(URIProvider _provider) external onlyOwner {
_setURIProvider(_provider);
}

/**
@notice Create a debt

@dev Hash (uint8(1), address(this), msg.sender, nonce) to make the id

@param _model Model of the debt
@param _owner Owner of the ERC721 and the debt
@param _oracle Oracle of the debt, if is address(0) the debt is in Token
in other case the debt use the oracle to get the rate
@param _data Array of bytes parameters, send to the Model contract with
the create function

@return The id if the debt
*/
function create(
Model _model,
address _owner,
address _oracle,
bytes calldata _data
) external returns (bytes32 id) {
// Increment the nonce of the sender
uint256 nonce = nonces[msg.sender]++;
// Calculate the id of the debt
id = keccak256(
abi.encodePacked(
uint8(1),
Expand All @@ -124,16 +152,17 @@ contract DebtEngine is ERC721Base, Ownable {
nonce
)
);

// Add the debt to the debts array
debts[id] = Debt({
error: false,
balance: 0,
creator: msg.sender,
model: _model,
oracle: _oracle
});

// Generate the ERC721
_generate(uint256(id), _owner);
// Execute the create function of the model
require(_model.create(id, _data), "Error creating debt in model");

emit Created({
Expand All @@ -143,13 +172,29 @@ contract DebtEngine is ERC721Base, Ownable {
});
}

/**
@notice Create a debt

@dev Hash (uint8(2), address(this), msg.sender, _model, _oracle, _salt, _data) to make the id

@param _model Model of the debt
@param _owner Owner of the ERC721 and the debt
@param _oracle Oracle of the debt, if is address(0) the debt is in Token
in other case the debt use the oracle to get the rate
@param _salt Add entropy to the hash id
@param _data Array of bytes parameters, send to the Model contract with
the create function

@return The id if the debt
*/
function create2(
Model _model,
address _owner,
address _oracle,
uint256 _salt,
bytes calldata _data
) external returns (bytes32 id) {
// Calculate the id of the debt
id = keccak256(
abi.encodePacked(
uint8(2),
Expand All @@ -161,16 +206,17 @@ contract DebtEngine is ERC721Base, Ownable {
_data
)
);

// Add the debt to the debts array
debts[id] = Debt({
error: false,
balance: 0,
creator: msg.sender,
model: _model,
oracle: _oracle
});

// Generate the ERC721
_generate(uint256(id), _owner);
// Execute the create function of the model
require(_model.create(id, _data), "Error creating debt in model");

emit Created2({
Expand All @@ -180,13 +226,29 @@ contract DebtEngine is ERC721Base, Ownable {
});
}

/**
@notice Create a debt

@dev Hash (uint8(3), address(this), msg.sender, _salt) to make the id

@param _model Model of the debt
@param _owner Owner of the ERC721 and the debt
@param _oracle Oracle of the debt, if is address(0) the debt is in Token
in other case the debt use the oracle to get the rate
@param _salt Add entropy to the hash id
@param _data Array of bytes parameters, send to the Model contract with
the create function

@return The id if the debt
*/
function create3(
Model _model,
address _owner,
address _oracle,
uint256 _salt,
bytes calldata _data
) external returns (bytes32 id) {
// Calculate the id of the debt
id = keccak256(
abi.encodePacked(
uint8(3),
Expand All @@ -195,16 +257,17 @@ contract DebtEngine is ERC721Base, Ownable {
_salt
)
);

// Add the debt to the debts array
debts[id] = Debt({
error: false,
balance: 0,
creator: msg.sender,
model: _model,
oracle: _oracle
});

// Generate the ERC721
_generate(uint256(id), _owner);
// Execute the create function of the model
require(_model.create(id, _data), "Error creating debt in model");

emit Created3({
Expand All @@ -214,6 +277,9 @@ contract DebtEngine is ERC721Base, Ownable {
});
}

/**
@notice Getter of id when use create function
*/
function buildId(
address _creator,
uint256 _nonce
Expand All @@ -228,6 +294,9 @@ contract DebtEngine is ERC721Base, Ownable {
);
}

/**
@notice Getter of id when use create2 function
*/
function buildId2(
address _creator,
address _model,
Expand All @@ -248,6 +317,9 @@ contract DebtEngine is ERC721Base, Ownable {
);
}

/**
@notice Getter of id when use create3 function
*/
function buildId3(
address _creator,
uint256 _salt
Expand All @@ -262,6 +334,18 @@ contract DebtEngine is ERC721Base, Ownable {
);
}

/**
@notice Pay a debt

@dev The contract takes the funds from the sender but the really payer is the _origin

@param _id Index of the debt
@param _amount The maximum amount of the payment, valued in the currency of the debt
@param _origin The originator of the payment
@param _oracleData Data of oracle to change the currency of debt to the Token

@return How much was really paid valued in the currency of the debt and in the token
*/
function pay(
bytes32 _id,
uint256 _amount,
Expand All @@ -272,18 +356,20 @@ contract DebtEngine is ERC721Base, Ownable {
// Paid only required amount
paid = _safePay(_id, debt.model, _amount);
require(paid <= _amount, "Paid can't be more than requested");

// Get the oracle
RateOracle oracle = RateOracle(debt.oracle);
if (address(oracle) != address(0)) {
// Convert

if (address(oracle) != address(0)) { // Debt in currency
// Read oracle
(uint256 tokens, uint256 equivalent) = oracle.readSample(_oracleData);
emit ReadedOracle(_id, tokens, equivalent);
// Convert the paid amount from currency of debt to Token
paidToken = _toToken(paid, tokens, equivalent);
} else {
} else { // Debt in the Token
paidToken = paid;
}

// Pull tokens from payer
// Pull tokens from payer(sender)
require(token.transferFrom(msg.sender, address(this), paidToken), "Error pulling payment tokens");

// Add balance to the debt
Expand All @@ -303,26 +389,40 @@ contract DebtEngine is ERC721Base, Ownable {
});
}

/**
@notice Pay a debt with token

@dev The contract takes the funds from the sender but the really payer is the _origin

@param id Index of the debt
@param amount The amount of the payment, valued in the Token
@param origin The originator of the payment
@param oracleData Data of oracle to change the currency of debt to the Token

@return How much was really paid valued in the currency of the debt and in the token
*/
function payToken(
bytes32 id,
uint256 amount,
address origin,
bytes calldata oracleData
) external returns (uint256 paid, uint256 paidToken) {
Debt storage debt = debts[id];
// Read storage
// Get the oracle
RateOracle oracle = RateOracle(debt.oracle);

uint256 equivalent;
uint256 tokens;
uint256 available;

// Get available <currency> amount
if (address(oracle) != address(0)) {
if (address(oracle) != address(0)) { // Debt in currency
// Read oracle
(tokens, equivalent) = oracle.readSample(oracleData);
emit ReadedOracle(id, tokens, equivalent);
// Convert the paid amount from Token to currency of debt
available = _fromToken(amount, tokens, equivalent);
} else {
} else { // Debt in the Token
available = amount;
}

Expand All @@ -331,10 +431,11 @@ contract DebtEngine is ERC721Base, Ownable {
require(paid <= available, "Paid can't exceed available");

// Convert back to required pull amount
if (address(oracle) != address(0)) {
if (address(oracle) != address(0)) { // Debt in currency
// Convert the paid amount from currency of debt to Token
paidToken = _toToken(paid, tokens, equivalent);
require(paidToken <= amount, "Paid can't exceed requested");
} else {
} else { // Debt in the Token
paidToken = paid;
}

Expand Down Expand Up @@ -372,6 +473,7 @@ contract DebtEngine is ERC721Base, Ownable {
uint256 tokens;
uint256 equivalent;
if (_oracle != address(0)) {
// Read oracle
(tokens, equivalent) = RateOracle(_oracle).readSample(_oracleData);
emit ReadedOracleBatch(_oracle, count, tokens, equivalent);
}
Expand Down Expand Up @@ -406,7 +508,8 @@ contract DebtEngine is ERC721Base, Ownable {

uint256 tokens;
uint256 equivalent;
if (_oracle != address(0)) {
if (_oracle != address(0)) {// Read oracle
// Read oracle
(tokens, equivalent) = RateOracle(_oracle).readSample(_oracleData);
emit ReadedOracleBatch(_oracle, count, tokens, equivalent);
}
Expand Down
Loading