Skip to content

Instantly share code, notes, and snippets.

@cNoveron
Created September 3, 2025 07:04
Show Gist options
  • Select an option

  • Save cNoveron/b7213aeba0c453bda0ebe12cd3e98e83 to your computer and use it in GitHub Desktop.

Select an option

Save cNoveron/b7213aeba0c453bda0ebe12cd3e98e83 to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "./XToken.sol";
/**
* @title Lendexe's xNativeToken Contract
* @notice XToken which wraps Iota
* @author Lendexe
*/
contract XNativeToken is XToken {
/**
* @notice Construct a new xNativeToken money market
* @param comptroller_ The address of the Comptroller
* @param interestRateModel_ The address of the interest rate model
* @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18
* @param name_ ERC-20 name of this token
* @param symbol_ ERC-20 symbol of this token
* @param decimals_ ERC-20 decimal precision of this token
* @param admin_ Address of the administrator of this token
*/
constructor(
ComptrollerInterface comptroller_,
InterestRateModel interestRateModel_,
uint256 initialExchangeRateMantissa_,
string memory name_,
string memory symbol_,
uint8 decimals_,
address payable admin_
) public {
// Creator of the contract is admin during initialization
admin = msg.sender;
initialize(
comptroller_,
interestRateModel_,
initialExchangeRateMantissa_,
name_,
symbol_,
decimals_
);
// Set the proper admin now that initialization is done
admin = admin_;
}
mapping(address => uint256) private lastBorrowAmount;
/*** User Interface ***/
/**
* @notice Sender supplies assets into the market and receives xTokens in exchange
* @dev Reverts upon any failure
*/
function mint() external payable {
(uint256 err, ) = mintInternal(msg.value);
requireNoError(err, "mint failed");
}
/**
* @notice Sender redeems xTokens in exchange for the underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemTokens The number of xTokens to redeem into underlying
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function redeem(uint256 redeemTokens) external returns (uint256) {
return redeemInternal(redeemTokens);
}
/**
* @notice Sender redeems xTokens in exchange for a specified amount of underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemAmount The amount of underlying to redeem
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {
return redeemUnderlyingInternal(redeemAmount);
}
/**
* @notice Sender borrows assets from the protocol to their own address
* @param borrowAmount The amount of the underlying asset to borrow
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function borrow(uint256 borrowAmount) external returns (uint256) {
lastBorrowAmount[msg.sender] = borrowAmount;
return borrowInternal(borrowAmount);
}
function getBorrowAmount(address user) external view returns (uint256) {
return lastBorrowAmount[user];
}
/**
* @notice Sender repays their own borrow
* @dev Reverts upon any failure
*/
function repayBorrow() external payable {
(uint256 err, ) = repayBorrowInternal(msg.value);
requireNoError(err, "repayBorrow failed");
}
/**
* @notice Sender repays a borrow belonging to borrower
* @dev Reverts upon any failure
* @param borrower the account with the debt being payed off
*/
function repayBorrowBehalf(address borrower) external payable {
(uint256 err, ) = repayBorrowBehalfInternal(borrower, msg.value);
requireNoError(err, "repayBorrowBehalf failed");
}
/**
* @notice The sender liquidates the borrowers collateral.
* The collateral seized is transferred to the liquidator.
* @dev Reverts upon any failure
* @param borrower The borrower of this xToken to be liquidated
* @param xTokenCollateral The market in which to seize collateral from the borrower
*/
function liquidateBorrow(address borrower, XToken xTokenCollateral)
external
payable
{
require(msg.sender == comptroller.liquidatorAddress(), "Only liquidator set by admin can liquidate!");
(uint256 err, ) = liquidateBorrowInternal(
borrower,
msg.value,
xTokenCollateral
);
requireNoError(err, "liquidateBorrow failed");
}
/**
* @notice The sender adds to reserves.
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/
function _addReserves() external payable returns (uint256) {
return _addReservesInternal(msg.value);
}
/**
* @notice Send Iota to xNativeToken to mint
*/
function() external payable {
(uint256 err, ) = mintInternal(msg.value);
requireNoError(err, "mint failed");
}
/*** Safe Token ***/
/**
* @notice Gets balance of this contract in terms of Iota, before this message
* @dev This excludes the value of the current message, if any
* @return The quantity of Iota owned by this contract
*/
function getCashPrior() internal view returns (uint256) {
(MathError err, uint256 startingBalance) = subUInt(
address(this).balance,
msg.value
);
require(err == MathError.NO_ERROR);
return startingBalance;
}
/**
* @notice Gets decimal number of the underlying token
* @return The decimal number of the underlying token
*/
function getUnderlyingDecimalsNumber() internal view returns (uint8) {
return decimals;
}
/**
* @notice Perform the actual transfer in, which is a no-op
* @param from Address sending the Iota
* @param amount Amount of Iota being sent
* @return The actual amount of Iota transferred
*/
function doTransferIn(address from, uint256 amount)
internal
returns (uint256)
{
// Sanity checks
require(msg.sender == from, "sender mismatch");
require(msg.value == amount, "value mismatch");
return amount;
}
function doTransferOut(address payable to, uint256 amount) internal {
/* Send the Iota, with minimal gas and revert on failure */
to.transfer(amount);
}
function requireNoError(uint256 errCode, string memory message)
internal
pure
{
if (errCode == uint256(Error.NO_ERROR)) {
return;
}
bytes memory fullMessage = new bytes(bytes(message).length + 5);
uint256 i;
for (i = 0; i < bytes(message).length; i++) {
fullMessage[i] = bytes(message)[i];
}
fullMessage[i + 0] = bytes1(uint8(32));
fullMessage[i + 1] = bytes1(uint8(40));
fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));
fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));
fullMessage[i + 4] = bytes1(uint8(41));
require(errCode == uint256(Error.NO_ERROR), string(fullMessage));
}
function approveUnderlying(address spender, uint256 amount) internal {
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment