/*
SPDX-License-Identifier: UNLICENSED
(c) Developed by AgroToken
This work is unlicensed.
*/
pragma solidity 0.7.5;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title AgroToken is token that refers to real grains
* AgroToken is a token admnistrated by AgroToken company
* (represented by admin Ethereum address variable in this Smart Contract).
* AgroToken performs all administrative
* functions based on grain documentations and certifications in partnership
* with agro traders (called Grain Oracles) and in complaince with local authorities.
* */
contract AgroToken is IERC20 {
using SafeMath for uint256;
//
// events
//
// mint/burn events
event Mint(address indexed _to, uint256 _amount, uint256 _newTotalSupply);
event Burn(address indexed _from, uint256 _amount, uint256 _newTotalSupply);
// admin events
event BlockLockSet(uint256 _value);
event NewAdmin(address _newAdmin);
event NewManager(address _newManager);
event GrainStockChanged(
uint256 indexed contractId,
string grainCategory,
string grainContractInfo,
uint256 amount,
uint8 status,
uint256 newTotalSupplyAmount
);
modifier onlyAdmin {
require(msg.sender == admin, "Only admin can perform this operation");
_;
}
modifier boardOrAdmin {
require(
msg.sender == board || msg.sender == admin,
"Only admin or board can perform this operation"
);
_;
}
modifier blockLock(address _sender) {
require(
!isLocked() || _sender == admin,
"Contract is locked except for the admin"
);
_;
}
struct Grain {
string category;
string contractInfo;
uint256 amount;
uint8 status;
}
uint256 override public totalSupply;
string public name;
uint8 public decimals;
string public symbol;
address public admin;
address public board;
uint256 public lockedUntilBlock;
uint256 public tokenizationFee;
uint256 public deTokenizationFee;
uint256 public transferFee;
mapping(address => uint256) public balances;
mapping(address => mapping(address => uint256)) public allowed;
Grain[] public grains;
/**
* @dev Constructor
*/
constructor() {
name = "AgroToken Corn Argentina";
decimals = 4;
symbol = "CORA";
lockedUntilBlock = 0;
admin = msg.sender;
board = 0xA01cD92f06f60b9fdcCCdF6280CE9A10803bA720;
totalSupply = 0;
balances[address(this)] = totalSupply;
}
/**
* @dev Add new grain contract to portfolio
* @param _grainCategory - Grain category
* @param _grainContractInfo - Grain Contract's details
* @param _grainAmount - amount of grain in tons
* @return success
*/
function addNewGrainContract(
string memory _grainCategory,
string memory _grainContractInfo,
uint256 _grainAmount
) public onlyAdmin returns (bool success) {
Grain memory newGrain = Grain(
_grainCategory,
_grainContractInfo,
_grainAmount,
1
);
grains.push(newGrain);
_mint(address(this), _grainAmount);
emit GrainStockChanged(
grains.length-1,
_grainCategory,
_grainContractInfo,
_grainAmount,
1,
totalSupply
);
success = true;
return success;
}
/**
* @dev Remove a contract from Portfolio
* @param _contractIndex - Contract Index within Portfolio
* @return True if success
*/
function removeGrainContract(uint256 _contractIndex) public onlyAdmin returns (bool) {
require(
_contractIndex < grains.length,
"Invalid contract index number. Greater than total grain contracts"
);
Grain storage grain = grains[_contractIndex];
require(grain.status == 1, "This contract is no longer active");
require(_burn(address(this), grain.amount), "Could not to burn tokens");
grain.status = 0;
emit GrainStockChanged(
_contractIndex,
grain.category,
grain.contractInfo,
grain.amount,
grain.status,
totalSupply
);
return true;
}
/**
* @dev Updates a Contract
* @param _contractIndex - Contract Index within Portfolio
* @param _grainCategory - Grain category
* @param _grainContractInfo - Grain Contract's details
* @param _grainAmount - amount of grain in tons
* @return True if success
*/
function updateGrainContract(
uint256 _contractIndex,
string memory _grainCategory,
string memory _grainContractInfo,
uint256 _grainAmount
) public onlyAdmin returns (bool) {
require(
_contractIndex < grains.length,
"Invalid contract index number. Greater than total grain contracts"
);
require(_grainAmount > 0, "Cannot set zero asset amount");
Grain storage grain = grains[_contractIndex];
require(grain.status == 1, "This contract is no longer active");
grain.category = _grainCategory;
grain.contractInfo = _grainContractInfo;
if (grain.amount > _grainAmount) {
_burn(address(this), grain.amount.sub(_grainAmount));
} else if (grain.amount < _grainAmount) {
_mint(address(this), _grainAmount.sub(grain.amount));
}
grain.amount = _grainAmount;
emit GrainStockChanged(
_contractIndex,
grain.category,
grain.contractInfo,
grain.amount,
grain.status,
totalSupply
);
return true;
}
/**
* @return Number of Grain Contracts in Portfolio
*/
function totalContracts() public view returns (uint256) {
return grains.length;
}
/**
* @dev ERC20 Transfer
* @param _to - destination address
* @param _value - value to transfer
* @return True if success
*/
function transfer(address _to, uint256 _value)
override
external
blockLock(msg.sender)
returns (bool)
{
address from = (admin == msg.sender) ? address(this) : msg.sender;
require(
isTransferValid(from, _to, _value),
"Invalid Transfer Operation"
);
balances[from] = balances[from].sub(_value);
uint256 serviceAmount = 0;
uint256 netAmount = _value;
(serviceAmount, netAmount) = calcFees(transferFee, _value);
balances[_to] = balances[_to].add(netAmount);
balances[address(this)] = balances[address(this)].add(serviceAmount);
emit Transfer(from, _to, netAmount);
emit Transfer(from, address(this), serviceAmount);
return true;
}
/**
* @dev ERC20 TransferFrom
* @param _from - source address
* @param _to - destination address
* @param _value - value
* @return True if success
*/
function transferFrom(address _from, address _to, uint256 _value)
override
external
blockLock(_from)
returns (bool)
{
// check sufficient allowance
require(
_value <= allowed[_from][msg.sender],
"Value informed is invalid"
);
require(
isTransferValid(_from, _to, _value),
"Invalid Transfer Operation"
);
// transfer tokens
balances[_from] = balances[_from].sub(_value);
uint256 serviceAmount = 0;
uint256 netAmount = _value;
(serviceAmount, netAmount) = calcFees(transferFee, _value);
balances[_to] = balances[_to].add(netAmount);
balances[address(this)] = balances[address(this)].add(serviceAmount);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(
_value,
"Value lower than approval"
);
emit Transfer(_from, _to, netAmount);
emit Transfer(_from, address(this), serviceAmount);
return true;
}
/**
* @dev ERC20 Approve token transfers on behalf of other token owner
* @param _spender - destination address
* @param _value - value to be approved
* @return True if success
*/
function approve(address _spender, uint256 _value)
override
external
blockLock(msg.sender)
returns (bool)
{
require(_spender != address(0), "ERC20: approve to the zero address");
address from = (admin == msg.sender) ? address(this) : msg.sender;
require((_value == 0) || (allowed[from][_spender] == 0), "Allowance cannot be increased or decreased if value is different from zero");
allowed[from][_spender] = _value;
emit Approval(from, _spender, _value);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address _spender, uint256 _subtractedValue) public virtual returns (bool) {
require(_spender != address(0), "ERC20: decreaseAllowance to the zero address");
address from = (admin == msg.sender) ? address(this) : msg.sender;
require(allowed[from][_spender] >= _subtractedValue, "ERC20: decreased allowance below zero");
_approve(from, _spender, allowed[from][_spender].sub(_subtractedValue));
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address _spender, uint256 _addedValue) public virtual returns (bool) {
require(_spender != address(0), "ERC20: decreaseAllowance to the zero address");
address from = (admin == msg.sender) ? address(this) : msg.sender;
_approve(from, _spender, allowed[from][_spender].add(_addedValue));
return true;
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address _owner, address _spender, uint256 _amount) internal virtual {
require(_owner != address(0), "ERC20: approve from the zero address");
require(_spender != address(0), "ERC20: approve to the zero address");
allowed[_owner][_spender] = _amount;
emit Approval(_owner, _spender, _amount);
}
/**
* @dev withdraw tokens collected after receive fees
* @param _to - destination address
* @param _value - value to transfer
* @return True if success
*/
function withdraw(address _to, uint256 _value)
external
boardOrAdmin
returns (bool)
{
address from = address(this);
require(
isTransferValid(from, _to, _value),
"Invalid Transfer Operation"
);
balances[from] = balances[from].sub(_value);
balances[_to] = balances[_to].add(_value);
emit Transfer(from, _to, _value);
return true;
}
/**
* @dev Mint new tokens. Can only be called by mana
* @param _to - destination address
* @param _value - value
* @return True if success
*/
function _mint(address _to, uint256 _value)
internal
onlyAdmin
returns (bool)
{
require(_to != address(0), "ERC20: mint to the zero address");
require(_to != admin, "Admin cannot mint tokens to herself");
uint256 serviceAmount;
uint256 netAmount;
(serviceAmount, netAmount) = calcFees(tokenizationFee, _value);
balances[_to] = balances[_to].add(netAmount);
balances[address(this)] = balances[address(this)].add(serviceAmount);
totalSupply = totalSupply.add(_value);
emit Mint(_to, netAmount, totalSupply);
emit Mint(address(this), serviceAmount, totalSupply);
emit Transfer(address(0), _to, netAmount);
emit Transfer(address(0), address(this), serviceAmount);
return true;
}
/**
* @dev Burn tokens
* @param _account - address
* @param _value - value
* @return True if success
*/
function _burn(address _account, uint256 _value)
internal
onlyAdmin
returns (bool)
{
require(_account != address(0), "ERC20: burn from the zero address");
uint256 serviceAmount;
uint256 netAmount;
(serviceAmount, netAmount) = calcFees(deTokenizationFee, _value);
totalSupply = totalSupply.sub(netAmount);
balances[_account] = balances[_account].sub(_value);
balances[address(this)] = balances[address(this)].add(serviceAmount);
emit Transfer(_account, address(0), netAmount);
emit Transfer(_account, address(this), serviceAmount);
emit Burn(_account, netAmount, totalSupply);
return true;
}
/**
* @dev Set block lock. Until that block (exclusive) transfers are disallowed
* @param _lockedUntilBlock - Block Number
* @return True if success
*/
function setBlockLock(uint256 _lockedUntilBlock)
public
boardOrAdmin
returns (bool)
{
lockedUntilBlock = _lockedUntilBlock;
emit BlockLockSet(_lockedUntilBlock);
return true;
}
/**
* @dev Replace current admin with new one
* @param _newAdmin New token admin
* @return True if success
*/
function replaceAdmin(address _newAdmin)
public
boardOrAdmin
returns (bool)
{
require(_newAdmin != address(0x0), "Null address");
admin = _newAdmin;
emit NewAdmin(_newAdmin);
return true;
}
/**
* @dev Change AgroToken fee values
* @param _feeType which fee is being changed. 1 = tokenizationFee, 2 = deTokenizationFee and 3 = transferFee
* @param _newAmount new fee value
* @return processing status
*/
function changeFee(uint8 _feeType, uint256 _newAmount) external boardOrAdmin returns (bool) {
require(_newAmount<=2, "Invalid or exceed white paper definition");
require(_feeType >0 && _feeType<=3, "Invalid fee type");
if (_feeType == 1) {
tokenizationFee = _newAmount;
} else if (_feeType == 2) {
deTokenizationFee = _newAmount;
} else if (_feeType == 3) {
transferFee = _newAmount;
}
return true;
}
/**
* @dev ERC20 balanceOf
* @param _owner Owner address
* @return True if success
*/
function balanceOf(address _owner) public override view returns (uint256) {
return balances[_owner];
}
/**
* @dev ERC20 allowance
* @param _owner Owner address
* @param _spender Address allowed to spend from Owner's balance
* @return uint256 allowance
*/
function allowance(address _owner, address _spender)
override
external
view
returns (uint256)
{
return allowed[_owner][_spender];
}
/**
* @dev Are transfers currently disallowed
* @return True if disallowed
*/
function isLocked() public view returns (bool) {
return lockedUntilBlock > block.number;
}
/**
* @dev Checks if transfer parameters are valid
* @param _from Source address
* @param _to Destination address
* @param _amount Amount to check
* @return True if valid
*/
function isTransferValid(address _from, address _to, uint256 _amount)
public
view
returns (bool)
{
if (_from == address(0)) {
return false;
}
if (_to == address(0) || _to == admin) {
return false;
}
bool fromOK = true;
bool toOK = true;
return
balances[_from] >= _amount && // sufficient balance
fromOK && // a seller holder within the whitelist
toOK; // a buyer holder within the whitelist
}
/**
* @dev Calculates AgroToken fees over mint, burn and transfer operations
* @param _fee value of the fee
* @param _amount amount involved in the transaction
* @return serviceAmount value to be paid to AgroToken
* @return netAmount amount after fees
*/
function calcFees(uint256 _fee, uint256 _amount) public pure returns(uint256 serviceAmount, uint256 netAmount ) {
serviceAmount = (_amount.mul(_fee)) / 100;
netAmount = _amount.sub(serviceAmount);
return (serviceAmount, netAmount);
}
}
{
"compilationTarget": {
"AgroToken.sol": "AgroToken"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"BlockLockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTotalSupply","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"contractId","type":"uint256"},{"indexed":false,"internalType":"string","name":"grainCategory","type":"string"},{"indexed":false,"internalType":"string","name":"grainContractInfo","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"status","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"newTotalSupplyAmount","type":"uint256"}],"name":"GrainStockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTotalSupply","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_newManager","type":"address"}],"name":"NewManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"string","name":"_grainCategory","type":"string"},{"internalType":"string","name":"_grainContractInfo","type":"string"},{"internalType":"uint256","name":"_grainAmount","type":"uint256"}],"name":"addNewGrainContract","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"board","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"calcFees","outputs":[{"internalType":"uint256","name":"serviceAmount","type":"uint256"},{"internalType":"uint256","name":"netAmount","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint8","name":"_feeType","type":"uint8"},{"internalType":"uint256","name":"_newAmount","type":"uint256"}],"name":"changeFee","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deTokenizationFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"grains","outputs":[{"internalType":"string","name":"category","type":"string"},{"internalType":"string","name":"contractInfo","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"isTransferValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedUntilBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_contractIndex","type":"uint256"}],"name":"removeGrainContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAdmin","type":"address"}],"name":"replaceAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockedUntilBlock","type":"uint256"}],"name":"setBlockLock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenizationFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalContracts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_contractIndex","type":"uint256"},{"internalType":"string","name":"_grainCategory","type":"string"},{"internalType":"string","name":"_grainContractInfo","type":"string"},{"internalType":"uint256","name":"_grainAmount","type":"uint256"}],"name":"updateGrainContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]