2018-10-24 12:52:11 +00:00
|
|
|
|
pragma solidity >=0.0;
|
2017-07-05 10:28:15 +00:00
|
|
|
|
|
|
|
|
|
import "./safeMath.sol";
|
|
|
|
|
import "./tokenDB.sol";
|
|
|
|
|
import "./module.sol";
|
|
|
|
|
|
|
|
|
|
contract thirdPartyPContractAbstract {
|
2018-08-07 20:12:52 +00:00
|
|
|
|
function receiveCorionPremiumToken(address, uint256, bytes calldata) external returns (bool, uint256) {}
|
|
|
|
|
function approvedCorionPremiumToken(address, uint256, bytes calldata) external returns (bool) {}
|
2017-07-05 10:28:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
contract ptokenDB is tokenDB {}
|
|
|
|
|
|
2020-05-20 16:25:23 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @title Corion Platform Premium Token
|
|
|
|
|
* @author iFA @ Corion Platform
|
|
|
|
|
*
|
|
|
|
|
*/
|
2017-07-05 10:28:15 +00:00
|
|
|
|
contract premium is module, safeMath {
|
2019-09-16 12:33:43 +00:00
|
|
|
|
function replaceModule(address payable addr) external override returns (bool success) {
|
2020-12-03 22:05:05 +00:00
|
|
|
|
require( super.isModuleHandler(payable(msg.sender)) );
|
2017-07-05 10:28:15 +00:00
|
|
|
|
require( db.replaceOwner(addr) );
|
|
|
|
|
super._replaceModule(addr);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
modifier isReady {
|
2018-06-21 11:58:38 +00:00
|
|
|
|
(bool _success, bool _active) = super.isActive();
|
2018-08-01 19:57:12 +00:00
|
|
|
|
require( _success && _active );
|
2017-07-05 10:28:15 +00:00
|
|
|
|
_;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
string public name = "Corion Premium";
|
|
|
|
|
string public symbol = "CORP";
|
|
|
|
|
uint8 public decimals = 0;
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
address public icoAddr;
|
|
|
|
|
tokenDB public db;
|
|
|
|
|
bool public isICO;
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
mapping(address => bool) public genesis;
|
2018-07-04 17:20:51 +00:00
|
|
|
|
|
2020-06-23 12:14:24 +00:00
|
|
|
|
constructor(bool forReplace, address payable moduleHandler, address dbAddress, address icoContractAddr, address[] memory genesisAddr, uint256[] memory genesisValue) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Setup function.
|
|
|
|
|
If an ICOaddress is defined then the balance of the genesis addresses will be set as well.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@forReplace This address will be replaced with the old one or not.
|
|
|
|
|
@moduleHandler Modulhandler’s address
|
|
|
|
|
@dbAddress Address of database
|
|
|
|
|
@icoContractAddr Address of ico contract.
|
|
|
|
|
@genesisAddr Array of the genesis addresses.
|
|
|
|
|
@genesisValue Array of the balance of the genesis addresses
|
|
|
|
|
*/
|
|
|
|
|
super.registerModuleHandler(moduleHandler);
|
2018-06-12 09:05:49 +00:00
|
|
|
|
require( dbAddress != address(0x00) );
|
2017-07-05 10:28:15 +00:00
|
|
|
|
db = ptokenDB(dbAddress);
|
|
|
|
|
if ( ! forReplace ) {
|
2018-07-12 18:07:16 +00:00
|
|
|
|
require( db.replaceOwner(address(this)) );
|
2017-07-05 10:28:15 +00:00
|
|
|
|
isICO = true;
|
|
|
|
|
icoAddr = icoContractAddr;
|
|
|
|
|
assert( genesisAddr.length == genesisValue.length );
|
|
|
|
|
for ( uint256 a=0 ; a<genesisAddr.length ; a++ ) {
|
|
|
|
|
genesis[genesisAddr[a]] = true;
|
|
|
|
|
require( db.increase(genesisAddr[a], genesisValue[a]) );
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Mint(genesisAddr[a], genesisValue[a]);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function closeIco() external returns (bool success) {
|
|
|
|
|
/*
|
|
|
|
|
Finishing the ICO. Can be invited only by an ICO contract.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success If the function was successful.
|
|
|
|
|
*/
|
|
|
|
|
require( isICO );
|
|
|
|
|
isICO = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* @notice `msg.sender` approves `spender` to spend `amount` tokens on its behalf.
|
|
|
|
|
* @param spender The address of the account able to transfer the tokens
|
|
|
|
|
* @param amount The amount of tokens to be approved for transfer
|
|
|
|
|
* @param nonce The transaction count of the authorised address
|
2019-10-21 22:05:34 +00:00
|
|
|
|
* @return success True if the approval was successful
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
|
|
|
|
function approve(address spender, uint256 amount, uint256 nonce) isReady external returns (bool success) {
|
|
|
|
|
/*
|
2018-08-01 19:57:12 +00:00
|
|
|
|
Authorize another address to use an exact amount of the principal’s balance.
|
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@spender Address of authorised party
|
|
|
|
|
@amount Token quantity
|
|
|
|
|
@nonce Transaction count
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success Was the Function successful?
|
|
|
|
|
*/
|
|
|
|
|
_approve(spender, amount, nonce);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* @notice `msg.sender` approves `spender` to spend `amount` tokens on its behalf and notify the spender from your approve with your `extraData` data.
|
|
|
|
|
* @param spender The address of the account able to transfer the tokens
|
|
|
|
|
* @param amount The amount of tokens to be approved for transfer
|
|
|
|
|
* @param nonce The transaction count of the authorised address
|
|
|
|
|
* @param extraData Data to give forward to the receiver
|
2019-10-21 22:05:34 +00:00
|
|
|
|
* @return success True if the approval was successful
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
2018-08-07 20:12:52 +00:00
|
|
|
|
function approveAndCall(address spender, uint256 amount, uint256 nonce, bytes calldata extraData) isReady external returns (bool success) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Authorize another address to use an exact amount of the principal’s balance.
|
|
|
|
|
After the transaction the approvedCorionPremiumToken function of the address will be called with the given data.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@spender Authorized address
|
|
|
|
|
@amount Token quantity
|
|
|
|
|
@extraData Extra data to be received by the receiver
|
|
|
|
|
@nonce Transaction count
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2018-07-10 07:18:19 +00:00
|
|
|
|
@success Was the Function successful?
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
|
|
|
|
_approve(spender, amount, nonce);
|
|
|
|
|
require( thirdPartyPContractAbstract(spender).approvedCorionPremiumToken(msg.sender, amount, extraData) );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function _approve(address spender, uint256 amount, uint256 nonce) isReady internal {
|
|
|
|
|
/*
|
2018-08-01 19:57:12 +00:00
|
|
|
|
Inner function to authorize another address to use an exact amount of the principal’s balance.
|
2017-07-05 10:28:15 +00:00
|
|
|
|
If the transaction count not match the authorise fails.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@spender Address of authorised party
|
|
|
|
|
@amount Token quantity
|
|
|
|
|
@nonce Transaction count
|
|
|
|
|
*/
|
|
|
|
|
require( msg.sender != spender );
|
|
|
|
|
require( db.balanceOf(msg.sender) >= amount );
|
|
|
|
|
require( db.setAllowance(msg.sender, spender, amount, nonce) );
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Approval(msg.sender, spender, amount);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
}
|
2018-07-04 17:20:51 +00:00
|
|
|
|
|
|
|
|
|
function allowance(address owner, address spender) public view returns (uint256 remaining, uint256 nonce) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Get the quantity of tokens given to be used
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@owner Authorising address
|
|
|
|
|
@spender Authorised address
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@remaining Tokens to be spent
|
|
|
|
|
@nonce Transaction count
|
|
|
|
|
*/
|
2018-06-21 11:58:38 +00:00
|
|
|
|
(bool _success, uint256 _remaining, uint256 _nonce) = db.getAllowance(owner, spender);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
require( _success );
|
|
|
|
|
return (_remaining, _nonce);
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* @notice Send `amount` Corion tokens to `to` from `msg.sender`
|
|
|
|
|
* @param to The address of the recipient
|
|
|
|
|
* @param amount The amount of tokens to be transferred
|
2019-10-21 22:05:34 +00:00
|
|
|
|
* @return success Whether the transfer was successful or not
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
|
|
|
|
function transfer(address to, uint256 amount) isReady external returns (bool success) {
|
|
|
|
|
/*
|
|
|
|
|
Launch a transaction where the token is sent from the sender’s address to the receiver’s address.
|
|
|
|
|
Transaction fee is going to be added as well.
|
|
|
|
|
If the receiver is not a natural address but also a person then she/he will be invited as well.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@to For who
|
|
|
|
|
@amount Amount
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success Was the function successful?
|
|
|
|
|
*/
|
|
|
|
|
bytes memory _data;
|
|
|
|
|
if ( isContract(to) ) {
|
|
|
|
|
transferToContract(msg.sender, to, amount, _data);
|
|
|
|
|
} else {
|
|
|
|
|
_transfer(msg.sender, to, amount);
|
|
|
|
|
}
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Transfer(msg.sender, to, amount, _data);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* @notice Send `amount` tokens to `to` from `from` on the condition it is approved by `from`
|
|
|
|
|
* @param from The address holding the tokens being transferred
|
|
|
|
|
* @param to The address of the recipient
|
|
|
|
|
* @param amount The amount of tokens to be transferred
|
2019-10-21 22:05:34 +00:00
|
|
|
|
* @return success True if the transfer was successful
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
|
|
|
|
function transferFrom(address from, address to, uint256 amount) isReady external returns (bool success) {
|
|
|
|
|
/*
|
|
|
|
|
Launch a transaction where we transfer from a given address to another one. It can only be called by an address which was allowed before.
|
|
|
|
|
Transaction fee will be charged too.
|
|
|
|
|
If the receiver is not a natural address but also a person then she/he will be invited as well
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@from From who?
|
|
|
|
|
@to For who?
|
|
|
|
|
@amount Amount
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success If the function was successful.
|
|
|
|
|
*/
|
|
|
|
|
if ( from != msg.sender ) {
|
2018-06-21 11:58:38 +00:00
|
|
|
|
(bool _success, uint256 _reamining, uint256 _nonce) = db.getAllowance(from, msg.sender);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
require( _success );
|
|
|
|
|
_reamining = safeSub(_reamining, amount);
|
|
|
|
|
_nonce = safeAdd(_nonce, 1);
|
|
|
|
|
require( db.setAllowance(from, msg.sender, _reamining, _nonce) );
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit AllowanceUsed(msg.sender, from, amount);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
}
|
|
|
|
|
bytes memory _data;
|
|
|
|
|
if ( isContract(to) ) {
|
|
|
|
|
transferToContract(from, to, amount, _data);
|
|
|
|
|
} else {
|
|
|
|
|
_transfer( from, to, amount);
|
|
|
|
|
}
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Transfer(from, to, amount, _data);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* @notice Send `amount` Corion tokens to `to` from `msg.sender` and notify the receiver from your transaction with your `extraData` data
|
|
|
|
|
* @param to The contract address of the recipient
|
|
|
|
|
* @param amount The amount of tokens to be transferred
|
|
|
|
|
* @param extraData Data to give forward to the receiver
|
2019-10-21 22:05:34 +00:00
|
|
|
|
* @return success Whether the transfer was successful or not
|
2017-07-05 10:28:15 +00:00
|
|
|
|
*/
|
2018-08-07 20:12:52 +00:00
|
|
|
|
function transfer(address to, uint256 amount, bytes calldata extraData) isReady external returns (bool success) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Launch a transaction where we transfer from a given address to another one.
|
|
|
|
|
After thetransaction the approvedCorionPremiumToken function of the receiver’s address is going to be called with the given data.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@to For who?
|
|
|
|
|
@amount Amount
|
|
|
|
|
@extraData Extra data that will be given to the receiver
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success If the function was successful.
|
|
|
|
|
*/
|
|
|
|
|
if ( isContract(to) ) {
|
|
|
|
|
transferToContract(msg.sender, to, amount, extraData);
|
|
|
|
|
} else {
|
|
|
|
|
_transfer( msg.sender, to, amount);
|
|
|
|
|
}
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Transfer(msg.sender, to, amount, extraData);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2018-07-14 21:42:01 +00:00
|
|
|
|
function transferToContract(address from, address to, uint256 amount, bytes memory extraData) internal {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Inner function in order to transact a contract.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@to For who?
|
|
|
|
|
@amount Amount
|
|
|
|
|
@extraData Extra data that will be given to the receiver
|
|
|
|
|
*/
|
|
|
|
|
_transfer(from, to, amount);
|
2018-06-21 11:58:38 +00:00
|
|
|
|
(bool _success, uint256 _back) = thirdPartyPContractAbstract(to).receiveCorionPremiumToken(from, amount, extraData);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
require( _success );
|
|
|
|
|
require( amount > _back );
|
|
|
|
|
if ( _back > 0 ) {
|
|
|
|
|
_transfer(to, from, _back);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function _transfer(address from, address to, uint256 amount) isReady internal {
|
|
|
|
|
/*
|
|
|
|
|
Inner function to launch a transaction.
|
|
|
|
|
During the ICO transactions are only possible from the genesis address.
|
|
|
|
|
0xa636a97578d26a3b76b060bbc18226d954cf3757 address is blacklisted.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@from From how?
|
|
|
|
|
@to For who?
|
|
|
|
|
@amount Amount
|
|
|
|
|
*/
|
2018-06-12 09:05:49 +00:00
|
|
|
|
require( from != address(0x00) && to != address(0x00) && to != 0xa636A97578d26A3b76B060Bbc18226d954cf3757 );
|
2017-07-05 10:28:15 +00:00
|
|
|
|
require( ( ! isICO) || genesis[from] );
|
|
|
|
|
require( db.decrease(from, amount) );
|
|
|
|
|
require( db.increase(to, amount) );
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function mint(address owner, uint256 value) external returns (bool success) {
|
|
|
|
|
/*
|
|
|
|
|
Generating tokens. It can be called only by ICO contract.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@owner Address
|
|
|
|
|
@value Amount.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success Was the Function successful?
|
|
|
|
|
*/
|
|
|
|
|
require( msg.sender == icoAddr || isICO );
|
|
|
|
|
_mint(owner, value);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function _mint(address owner, uint256 value) isReady internal {
|
|
|
|
|
/*
|
|
|
|
|
Inner function to create a token.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@owner Address of crediting the token.
|
|
|
|
|
@value Amount
|
|
|
|
|
*/
|
|
|
|
|
require( db.increase(owner, value) );
|
2018-06-27 08:35:38 +00:00
|
|
|
|
emit Mint(owner, value);
|
2017-07-05 10:28:15 +00:00
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
function isContract(address addr) internal returns (bool success) {
|
|
|
|
|
/*
|
|
|
|
|
Inner function in order to check if the given address is a natural address or a contract.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@addr The address which is needed to be checked.
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@success Is the address crontact or not
|
|
|
|
|
*/
|
|
|
|
|
uint256 _codeLength;
|
|
|
|
|
assembly {
|
|
|
|
|
_codeLength := extcodesize(addr)
|
|
|
|
|
}
|
|
|
|
|
return _codeLength > 0;
|
|
|
|
|
}
|
2018-07-04 17:20:51 +00:00
|
|
|
|
|
|
|
|
|
function balanceOf(address owner) public view returns (uint256 value) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Token balance query
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@owner Address
|
|
|
|
|
@value Balance of address
|
|
|
|
|
*/
|
|
|
|
|
return db.balanceOf(owner);
|
|
|
|
|
}
|
2018-07-04 17:20:51 +00:00
|
|
|
|
|
|
|
|
|
function totalSupply() public view returns (uint256 value) {
|
2017-07-05 10:28:15 +00:00
|
|
|
|
/*
|
|
|
|
|
Total token quantity query
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
@value Total token quantity
|
|
|
|
|
*/
|
|
|
|
|
return db.totalSupply();
|
|
|
|
|
}
|
2018-08-01 19:57:12 +00:00
|
|
|
|
|
2017-07-05 10:28:15 +00:00
|
|
|
|
event AllowanceUsed(address indexed spender, address indexed owner, uint256 indexed value);
|
|
|
|
|
event Mint(address indexed addr, uint256 indexed value);
|
|
|
|
|
event Burn(address indexed addr, uint256 indexed value);
|
|
|
|
|
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
|
|
|
|
event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _extraData);
|
|
|
|
|
}
|