When I call the function giveFifteenthTokens
in my contract problem2_bank
, it does not transfer tokens from msg.sender
to recipient
. Why?
My Files:
LoanToken.sol
pragma solidity ^0.5.8;
import "browser/ERC20.sol";
contract LoanToken {
// Data of the Token
uint private _totalSupply = 1000;
string public name = "LoanToken";
string public symbol = "LT";
uint8 public decimals = 0;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
mapping (address => uint) public _balances;
mapping (address => mapping (address => uint256)) private _allowances;
constructor() public {
_balances[msg.sender] = totalSupply();
emit Transfer(address(0), msg.sender, totalSupply());
}
// total amount of tokens which can be spent, when this limit will be reached, the smart contract will refuse to create new tokens
function totalSupply() public view returns (uint) {
return _totalSupply;
}
// returns how many tokens specified address has
function balanceOf(address _owner) public view returns (uint256) {
return _balances[_owner];
}
// takes amount of tokens from msg.sender and send them to recipient
function transfer(address recipient, uint256 amount) public returns (bool)
{
if (_balances[msg.sender] >= amount && amount > 0) {
_balances[recipient] += amount;
_balances[msg.sender] -= amount;
emit Transfer(msg.sender, recipient, amount);
return true;
} else { return false; }
}
// returns the amount of tokens with which spender can still withdraw from owner.
function allowance(address owner, address spender) public view returns (uint256)
{
return _allowances[owner][spender];
}
// approved spender is able to withdraw his balance so much as he want, but not more that amount
function approve(address spender, uint256 amount) public returns (bool)
{
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
// transfer tokens from sender and send them to recipient
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool)
{
if (_balances[sender] >= amount && _allowances[sender][msg.sender] >= amount && amount > 0) {
_balances[recipient] += amount;
_balances[sender] -= amount;
_allowances[sender][msg.sender] -= amount;
emit Transfer(sender, recipient, amount);
return true;
} else { return false; }
}
}
problem2_bank.sol
pragma solidity ^0.5.8;
import "browser/LoanToken.sol";
contract problem2_bank {
address private _owner;
LoanToken public loanToken;
uint private loansCount = 0;
uint private guaranteesCount = 0;
mapping (uint => Loan) private loans;
mapping (uint => Guarantee) private guarantees;
mapping (uint => address payable) private lenders;
constructor(address loanTokenAddress) public
{
_owner = msg.sender;
loanToken = LoanToken(loanTokenAddress);
}
// if(msg.sender == address(0))
// msg.value, payable, transfer() <=== refactor it
struct Loan {
address payable loanee;
uint etherBorrow;
uint index;
uint payBackDate;
uint etherInterest;
bool _isGuaranteeProvided;
bool _isLoanProvided;
bool _isLoanExist;
}
struct Guarantee {
address payable guarantor;
uint etherInterest;
uint loanIndex;
bool _isWaitingForHandling;
bool _isGuaranteeExist;
}
function getAllowance(address spender) public view returns(uint)
{
return loanToken.allowance(msg.sender, spender);
}
function giveFifteenthTokens(address spender) public returns(bool)
{
require(msg.sender == _owner, "You are not owner of that smart contract");
require(spender != _owner, "The owner of the smart contract can't receive tokens from himself");
// require(
// loanToken.approve(spender, 15),
// "You don't receive approval from loanToken for that address on 15 LoanTokens");
// require(
// loanToken.transfer(spender, 15),
// "Your transfer was failed");
// loanToken.approve(spender, 15);
loanToken.transfer(spender, 15);
return true;
}
function getBalanceOfTokens(address account) public view returns(uint)
{
return loanToken.balanceOf(account);
}
function requestLoan(uint etherBorrow, uint8 payBackDate, uint8 etherInterest) public
{
Loan memory loan = Loan({loanee: msg.sender, index: loansCount, etherBorrow: etherBorrow,
payBackDate: now + (payBackDate * 1 days), etherInterest: etherInterest,
_isGuaranteeProvided: false, _isLoanProvided: false, _isLoanExist: true});
loans[loansCount] = loan;
loansCount++;
}
function provideGuarantee(uint index, uint8 guaranteeInterest) public // payable means that value should have ether
{
require(
index < loansCount,
"This index does not exist");
require(loans[index].loanee != msg.sender,
"The borrower can't provide a guarantee to himself");
require(lenders[index] != msg.sender,
"The lender can't provide guarantee for the loan");
require(!loans[index]._isGuaranteeProvided,
"This loan already has a guarantee");
require(guaranteesCount < loansCount || !guarantees[index]._isWaitingForHandling,
"This guarantee already waiting for handling of borrower");
require(guaranteeInterest > 0,
"Too low interest");
require(
loans[index]._isLoanExist,
"This loan does not exist");
require(
!guarantees[index]._isGuaranteeExist,
"This guarantee does exist");
Guarantee memory guarantee = Guarantee({guarantor: msg.sender, etherInterest: guaranteeInterest,
loanIndex: index, _isWaitingForHandling: true, _isGuaranteeExist: true});
guarantees[index] = guarantee;
guaranteesCount++;
}
function handleGuarantee(uint index, bool isGuaranteeProvided) public
{
require(
index < loansCount,
"This index does not exist");
require(loans[index].loanee == msg.sender,
"This is not your loan");
require(guarantees[index]._isWaitingForHandling,
"Guarantee already processed");
require(
loans[index]._isLoanExist,
"This loan does not exist");
require(
guarantees[index]._isGuaranteeExist,
"This guarantee does not exist");
loans[index]._isGuaranteeProvided = isGuaranteeProvided;
guarantees[index]._isWaitingForHandling = false;
if(!loans[index]._isGuaranteeProvided){
guarantees[index].guarantor.transfer(loans[index].etherBorrow); // transfer eather from smart contract to guarantor back
require(
loanToken.approve(msg.sender, loans[index].etherBorrow),
"You don't receive approval from loanToken for this amount");
require(
loanToken.transferFrom(_owner, msg.sender, loans[index].etherBorrow),
"You don't receive tokens from loanToken for this amount");
delete guarantees[index];
guaranteesCount--;
}
}
function getLoansInfo(uint index) public view returns(uint, bool, uint, address payable) {
require(
lenders[index] == msg.sender,
"You are not a leander of this loan");
require(
index < loansCount,
"This index does not exist");
require(
loans[index]._isLoanExist,
"This loan does not exist");
return(loansCount, // count of loans
loans[index]._isGuaranteeProvided, // was the guarantee provided
loans[index].etherBorrow * loans[index].etherInterest / 100, // interest of loan, which should receive lender in ether
guarantees[index].guarantor); // address of guarantor
}
function provideLoanForLoanee(uint index) public payable
{
require(
lenders[index] == address(0),
"The lender for this loan is already exist");
require(
loans[index].loanee != msg.sender,
"You are not a lender");
require(
guarantees[index].guarantor != msg.sender,
"You are not a lender");
require(
index < loansCount,
"This index does not exist");
require(
loans[index]._isGuaranteeProvided,
"This loan doesn't have a guarantee");
require(
!loans[index]._isLoanProvided,
"This loan is already provided");
require(
loans[index]._isLoanExist,
"This loan does not exist");
require(
msg.value == loans[index].etherBorrow,
"You don't have enough ether");
require(
loanToken.allowance(msg.sender, loans[index].loanee) == loans[index].etherBorrow, // msg.value == loans[index].etherBorrow
"You don't have enough ether");
loans[index].loanee.transfer(loans[index].etherBorrow); // transfer eather from lender to loanee
loans[index]._isLoanProvided = true;
lenders[index] = msg.sender;
}
function isBorrowerTransferEtherAtTime(uint index) public
{
require(
lenders[index] != address(0),
"Loan doesn't have a lender");
require(
lenders[index] == msg.sender,
"You are not leander of this loan");
require(
index < loansCount,
"This index does not exist");
require(
loans[index]._isLoanProvided,
"This loan has not yet been provided");
require(
loans[index]._isLoanExist,
"This loan does not exist");
// if should be executed, when borrower doesn't provide ether and interest at time
if(loans[index].payBackDate * 1 days <= now){
// lender receive back his ether(this amount from smart contract, which was locked)
lenders[index].transfer(loans[index].etherBorrow);
// remove the loan
delete loans[index];
loansCount--;
// remove the guarantee
delete guarantees[index];
guaranteesCount--;
// remove the lender
delete lenders[index];
}
}
function payBackLoan(uint index) public payable {
require(
index < loansCount,
"This index does not exist");
require(loans[index].loanee == msg.sender,
"This is not your loan");
require(
loans[index]._isLoanProvided,
"This loan was not provided");
require(
loans[index]._isLoanExist,
"This loan does not exist");
require(
guarantees[index]._isGuaranteeExist,
"This guarantee does not exist");
uint amount = (loans[index].etherBorrow + loans[index].etherBorrow * guarantees[index].etherInterest / 100) +
(loans[index].etherBorrow * loans[index].etherInterest / 100);
require(
msg.value == amount, // amount => guarantor interest + lender interest
"You should to pay back amount with interest");
// transfer ether with interest from smart contract to guarantor back
guarantees[index].guarantor.transfer(loans[index].etherBorrow + loans[index].etherBorrow * guarantees[index].etherInterest / 100);
// transfer ether with interest from smart contract to lender
lenders[index].transfer(loans[index].etherBorrow + loans[index].etherBorrow * loans[index].etherInterest / 100);
// remove the loan
delete loans[index];
loansCount--;
// remove the guarantee
delete guarantees[index];
guaranteesCount--;
// remove the lender
delete lenders[index];
}
}
problem2_bank
.