With the ascendancy of blockchains and cryptocurrencies you do not want to be left out of this right?
In this article I will teach to you how to create a smart contract to receive donations using solidity.
What is Solidity?
Solidity is an object-oriented programming language for writing smart contracts. It is used for implementing smart contracts on various blockchain platforms, most notably, Ethereum. Wikipedia
Pragma Version
First thing we will do after creating a .sol file(solidity extension) is define a pragma version, this is for solidity to understand which version our contract is in and to compile it correctly.
DonateContract.sol
pragma solidity ^0.8.0;
Starting the contract
Now we are going to start our contract, for this we need to call contract + ContractName for solidity to understand where our contract code will be.
DonateContract.sol
pragma solidity ^0.8.0;
contract DonateContract {
//the code will stay here
}
Variables
Solidity supports three types of variables:
- State variables: variables whose values are permanently stored in a contract storage.
- Local variables: variables whose values are present till function is executing.
- Global variables: special variables exists in the global namespace used to get information about the blockchain.
We are going to create two types of state variables:
The variables are written as follows: type + variableName
- totalDonations: totalDonations is a uint that stores the amount of donations that have already been made.
- owner: owner is of the payable address type that will be the creator of the contract that will receive the donations.
Obs: all addresses that will accept payment or make payment must be of the payable type.
DonateContract.sol
pragma solidity ^0.8.0;
contract DonateContract {
uint totalDonations; // the amount of donations
address payable owner; // contract creator's address
}
Using the constructor
In our solidity contract we have a constructor to set up our contract and set some standards.
We will define who will be the owner of our contract and that it will be of the payable type, in this case the creator of the contract.
DonateContract.sol
pragma solidity ^0.8.0;
contract DonateContract {
uint totalDonations; // the amount of donations
address payable owner; // contract creator's address
//contract settings
constructor() {
owner = payable(msg.sender); // setting the contract creator
}
}
Creating our first function
Now we are going to create a simple function to return the amount of donations.
DonateContract.sol
pragma solidity ^0.8.0;
contract DonateContract {
uint totalDonations; // the amount of donations
address payable owner; // contract creator's address
//contract settings
constructor() {
owner = payable(msg.sender); // setting the contract creator
}
// public function to return the amount of donations
function getTotalDonations() view public returns(uint) {
return totalDonations;
}
}
Our function takes three parameters:
- public: This function is of the public type and can be called by anyone.
- view: It means that this function is a view-only function and does not do any transactions and you don't need to pay gas to use it.
- returns(uint): Here we are saying that the function will return something of type uint.
Creating function to make donation
Now we are going to make a function to make the donation, we need say that it is public and payable.
DonateContract.sol
pragma solidity ^0.8.0;
contract DonateContract {
uint totalDonations; // the amount of donations
address payable owner; // contract creator's address
//contract settings
constructor() {
owner = payable(msg.sender); // setting the contract creator
}
//public function to make donate
function donate() public payable {
(bool success,) = owner.call{value: msg.value}("");
require(success, "Failed to send money");
}
// public function to return total of donations
function getTotalDonations() view public returns(uint) {
return totalDonations;
}
}
Obs: you can use nonReentrant to give more secure to your contract.
In our donate function we use owner.call{value: msg.value}("")
to make a payment to owner of contract, where msg.value
(global variable) is the value we want to send as a donation.
Then we get the call
return to check if the transfer was successful using require
.
The require
takes as the first parameter the variable success
saying whether a transaction was successful or not, thus returning an error or proceeding. The second parameter will be the message sent in case of error.
Ready!! we have our first contract ready. 😁🥳
For more content you can follow me here and on my twitter:
Twitter
Top comments (15)
A few things. The owner might be who deployed the contract but not the one expecting the donations. Anyone can call your donate method. If the address points to another contract that could give errors, your eth will be burned/lost. Transfer is not recommended anymore. You should use Call and check for the result. If the result is false, you revert the transaction. Great start anyways!
thanks, i will make these fixes!!
I made these corrections in case you want to check
Yes, that is perfect!
It would be amazing if there're a bit more details on hosting the contract on testnest and mainnest. But it's still a great article. Keep up the good work mate
Thanks for the feedback, I will create an article to make a deploy for the testnet!!
cool! deploying to the main nest is a pain actually. The gas fee is insane nowadays.
Nice post.
I have a questiopn please, i tried running the test locally to test my contract but i keep getting this error "Failed to send money" what do you think could be the casue pls. @emanuelferreira
Thank you!
how are you sending money using the web3? you need to pass the value on your web3 call function.
Thanks for the example. I was trying to out this contract, but I keep getting a weird error - I'm sure it's something simple that I'm missing here.
I deployed to Rinkeby Testnet using remix... then I loaded the contract and ABI into app.mycrypto.com/interact-with-con... - but when I try to send a donation, I keep getting this error:
"Something went wrong: insufficient funds for intrinsic transaction cost. Make sure you've filled everything out correctly and try again. If this error persists, please visit our Knowledge Base for further assistance."
I have plenty of test ETH in my account. I have tried to send ETH directly to the contract and it also fails. What am I doing wrong?
One strange thing is that I can make a donation of "0 ETH" but if I add ANY amount - such as 0.0001 ETH - I get the same error as above. Gas costs are only 0.000094ETH so it really can't be the issue. Does my contract need to be deployed with ETH in it?
Hello, is it possible to use an ERC20 token inside a function of an ERC721 token?
To better explain what I want to do is as follows.
Before minting an ERC721 token (Item of my game) I want to check if the player has my token (ERC20) in his wallet, if he has he could mint it...
Is it possible to do that? Thanks.
Hey RoNi, yes!
on your ERC721 mint function you need to connect with your ERC20 contract and verify the balance of the user
sick bro! Keep going!
Can make a donate in USDT instead of ETH ?