I am using Solidity to deploy smartcontract to a test Ethereum network launched by Ganache. I read some demo code of contract and one of them looks like:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.4;
pragma experimental ABIEncoderV2;
contract Ledger {
struct TransferRequest {
string title;
uint256 amount;
string bsb;
string accountName;
string accountNumber;
}
mapping(address => uint256) balances;
address payable owner;
event Transfered(bool _success, address _from, address _to, uint256 amount);
constructor() payable {
owner = payable(msg.sender);
balances[tx.origin] = 10000;
}
function sendCoin(address payable receiver, uint256 amount)
payable public
{
require(msg.sender == owner);
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfered(true, msg.sender, receiver, amount);
}
function getBalance(address addr) public view returns (uint256) {
return balances[addr];
}
}
As you can see above that the contract manages the balance by itself rather than using the balance from the blockchain. There is no real ether transfer inside sendCoin method. Does this mean there is no real transaction in the blockchain. Then what the point of building a contract like that. What would be the relationship between balance managed by blockchain and balance managed by contract?
the contract manages the balance by itself rather than using the balance from the blockchain
Each state change (in this case change of balances storage property value) is recorded on the blockchain. So the contract is reading the balance from the blockchain.
However, the way Ethereum network is designed, an address can only have few properties - its bytecode (non-zero bytecode means it's a smart contract), its balance, and few others. Since there's only one property for balance (and not a list of balances), it's used for the native ETH balance. Any token balances are stored in the contracts of the respective tokens.
You can read more about the token balance storage design in the final version of ERC-20 and the linked documents. This is the first standard that introduced tokens on Ethereum.
Related
// contracts/transferownership.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract transferownership is ERC20, Ownable {
uint256 lastpresence;
uint256 amount = balanceOf(msg.sender);
constructor(uint256 initialSupply) ERC20("interorm", "intr") {
_mint(msg.sender, initialSupply);
}
function presence() public onlyOwner {
lastpresence = block.timestamp;
}
function changeOwnership(address newowner) public {
require(lastpresence < block.timestamp - 356 days);
transfer(newowner, amount);
_transferOwnership(newowner);
lastpresence = block.timestamp;
}
}
//The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC20: transfer amount exceeds balance".
Debug the transaction to get more information.
//basically the program should transfer the whole amount of money
and then change ownership but im getting this error
everytime i call the changeownership function
To fix it, simply declare the amount variable in the changeOwnership function. That is before you call the transfer method.
uint256 amount = balanceOf(msg.sender);
transfer(newowner, amount);
Ensure that you set the changeOwnership function as payable.
function changeOwnership(address newowner) payable public {
Explanation: When you debug the function, the way you have it originally, you will find that the value=0, this is because the amount declaration in the global variable is not called in the stack when the transfer method is called.
To make the amount available in the call stack, you will have to parse it in the function.
could anyone help me with this??
used online remix in order to create a calucator using following criteria
Add Log of transactions using the event/emit
Each time one of the methods is called you will add
the address (msg.sender)
the action (“add”, “subtract”…)
the number
ii. Create a modifier “isOwner” like we did in class and add it to all the
methods in the calculator.
iii. Add a check using require or revert for the divide method to make sure
you are not dividing by zero (0).
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract Calculator{
mapping(address => uint256) public transactions;
address public owner;
address[] public transList; //// Showing to modify this line of code
constructor() {
owner = msg.sender;
}
modifier isOwner() {
require(msg.sender == owner, "Sender is not Owner");
_;
}
function whoIsOwner() public isOwner view returns (address) {
return owner;
}
uint256 public total =0;
uint256 public current_total =0;
function add(uint256 _amount) isOwner public{
total = total + _amount;
transList.push(msg.sender);
transList.push("add"); /// Error in this line
transList.push(_amount);
}
I created smart contract to transfer ETH from one account to another, ETH deduction occurs but send to other address(which is not specified). Please help me to resolve this problem.
//SPDX-License-Identifier:MIT
pragma solidity ^0.8.12;
contract ETH{
address public buyer;
uint public amt;
address public seller;
constructor(){
seller = msg.sender;
}
function add(address payable _buyer) payable public{
buyer = _buyer;
payable(buyer).transfer(amt);
}
function bal() view public returns(uint){
return buyer.balance;
}
function s() payable public returns(uint){
return msg.value;
}
}
The default value of amt is 0 and your code does not set this property (to a non-zero value) anywhere.
Which effectively makes your .transfer(amt) function to send 0 ETH to the buyer and keep all the ETH, that you sent along with the transaction, in the contract.
If you want to redirect the sent amount, there's the msg.value global variable, which reflects the current value sent with the transaction.
payable(buyer).transfer(msg.value);
I have a problem related to refund the users entered inside the solidity contract. I don't, have any idea if is possible iterate all the players of my contract and refund all of them with all the balance.I read in some tutorials, iterate inside the solidity contract cost a lot of gas depends of the numer of iterations.
contract Lottery{
address payable public manager;
string public name; // short name (up to 32 bytes)
address [] players;
uint256 nTickets;
address winner;
bool enable;
uint256 minimunContribution;
mapping(address => uint) public balances;
constructor (string memory LotteryName, uint minimun, address payable creator) public {
manager = creator;
name = LotteryName;
winner = address(0);
enable = true;
minimunContribution = minimun;
}
modifier restricted() {
require(msg.sender == manager, "Access forbidden");
_;
}
function enterInToLottery() public payable {
require(msg.value > minimunContribution && enable == true, "Insufficient funds to allow transfer");
players.push(msg.sender);
balances[msg.sender] += msg.value;
nTickets++;
}
//this function refund
function paybackEther(bool newfinished) public restricted {
enable = !newfinished;
selfdestruct(msg.sender);
}}
Thanks in advance to all.
Yes that can be problematic as it will use a lot of gas and may even hit limits. To solve this it is better to allow the users to withdraw the balance themselves, so they pay for the gas. Or in fact you can allow anybody to make that call. So you can offer a call refund(account:uint256) which transfers the balance (if any) to given account. Note that this would not be using msg.sender, so that anybody (including the admin) can do this transfer.
Keep in mind they need to know that they have a balance, so make sure you're emitting an event or similar. Also provide a balanceOf(address) call so they can check.
Hope this makes sense & works for you.
I am making a simple smart contract that is essentially a ledger that people can sign with a string (UI to come) and then pass onto a next person (using their ether address). I just wanted to create something that could be passed from person to person while recording its journey.
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time). Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
my solidity code so far:
pragma solidity ^0.4.4;
contract Pass{
mapping(address => bool) ownership;
mapping(address => string) notes;
constructor(address genesis) public {
ownership[genesis] = true; //this address starts with it
}
function checkOwnership(address p) public view returns(bool){
if(ownership[p]){
return true;
}
return false;
}
function sign(string signedNote) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
notes[msg.sender] = signedNote;
return 1;
}
return 0;
}
function pass(address recipient) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
ownership[msg.sender] = 0;
ownership[recipient] = 1;
return 1;
}
return 0;
}
function viewNotes(address participant) public returns(string){ // signed note on success nothing on fail
if(notes[participant] !== 0){
return (notes(participant));
}
}
}
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time)
This is a common pattern known as the owner pattern. You can simplify this by simply keeping track of a single owner address and updating that, instead of using a mapping, since you only care about the current owner. Something as simple as:
address public owner;
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
constructor() {
owner = msg.sender;
}
function transferOwnership(address _owner) onlyOwner {
owner = _owner;
}
Open Zeppelin has a more complete implementation of ownership here.
Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Transactions do not require ether movement. You can call any public/external function on your contract with a 0 value transaction, and pass data to it. The transaction will execute on the blockchain like any other, and run the code you invoke within the contract.
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
You are already checking is msg.sender matches the whitelisted address. For basic transactions, this means that the transaction has been signed by the address in msg.sender (msg.sender can also be a contract, if another contract calls yours. To check who actually signed the transaction in all scenarios, you must use tx.origin).