Solidity is an object-oriented high-level programming language that is personalized exclusively for building smart contracts. It draws inspiration from other programming languages like JavaScript, Python, and C++, making it easy to learn.
We can easily send Ethereum to a message sender using Solidity programming language just by writing a few lines of code. Sending Ethereum to a message sender means sending it to the address of the individual who initiated the transaction.
Setting up a Solidity project can be difficult for beginners but this particular functionality of sending ether is quite easy. Let’s first understand some terms to make the whole process more easy and understandable for you.
Also Read: Top 5 Programming Languages to Build Smart Contracts
What is msg.sender in Solidity?
To identify the initiator of a transaction or current call, we can make use of the globally available msg object. This object has a couple of properties tied to it. For example, we have a value, a sender, gas, and a data property on it. The one we need is the msg.sender property.
The msg.sender is the address that has called or initiated a function or created a transaction. Now, this address could be of a contract or even a person like you and me.
Creating a Sample Lottery Smart Contract
To understand how to send Ethereum to a message sender, we need a small smart contract for demonstration purposes. Let’s create a simple lottery smart contract.
- To begin with, let us create a contracts directory in the main project directory.
- Next, we will create a file named Lottery.sol to house the code of the contract.
Lottery.sol:
pragma solidity ^0.4.17;
contract Lottery {
address public manager;
address[] public players;
function Lottery() public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint256) {
return uint256(keccak256(block.difficulty, now, players));
}
function pickWinner() public {
require(manager == msg.sender);
uint256 index = random() % players.length;
players[index].transfer(this.balance);
players = new address[](0);
}
function getPlayers() public view returns (address[]) {
return players;
}
}
Code Explanation:
The Solidity part of the smart contract is complete. It is time for a short explanation of the code so you understand better what is going on here.
- The contract starts with declaring 2 variables – one is the address of the manager of the lottery and the other is an array of addresses of the players of the lottery.
- We then immediately set the manager variable’s value as msg.sender indicating the person that has created the contract (the manager).
- We then create an enter() function that called by anyone who wishes to enter. Even the manager himself can enter. This function requires the participant to pay at least 0.01 ether to be able to enter and get his/her address added in the array of players.
- We then create the random() function which you must have noticed is a private function because we do not really want anyone outside the contract to call it. This random number generator creates a random number to be able to select a winner of the lottery. It returns an unsigned integer value. It takes the block difficulty score, the current time and date, and the players to generate a random integer.
- Next, we create a pickWinner() function that can be only by the manager. We do a small authentication here using the require() function again. The random number is then taken and passed into a mod operation against the length of the players array. This result is stored in a variable named index. The index is now the index number of the player that is the winner. We then immediately transfer the remaining balance of the contract to the winner. We use the transfer(this.balance) function for this. We also immediately reset the state of our contract without having to redeploy it over and over again by setting the player’s arrays length to 0.
- We also have a getPlayer() function to retrieve the array of players.
Creating the Compile Script for the Contract
Now, we have to create a compile script using Solc to compile Solidity code to retrieve the ABI and bytecode of the smart contract. These two are eventually deployed on the blockchain and can be read by the browser.
compile.js:
const path = require("path");
const fs = require("fs");
const solc = require("solc");
const lotteryPath = path.resolve(__dirname, "contracts", "Lottery.sol");
const source = fs.readFileSync(lotteryPath, "utf8");
module.exports = solc.compile(source, 1).contracts[":Lottery"];
Note: Make sure you have created the compile script file directly in the main project directory.
Creating the Deploy Script for the Smart Contract
We shall now write the deploy script to be able to deploy the contract on the Rinkeby test network. Similar to the compile script, let’s create the deploy script in the main project directory.
deploy.js:
const HDWalletProvider = require('@truffle/hdwallet-provider');
const Web3 = require('web3');
const { interface, bytecode } = require('./compile.js');
const provider = new HDWalletProvider(
'key shrimp shell dump about fog death unit hard find doomy surprise,
'https://rinkeby.infura.io/v3/900629bb1516987e9a08e762ef085a1a'
);
const web3 = new Web3(provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log(`Attempting to deploy from account: ${accounts[0]}`);
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode })
.send({ gas: '1000000', from: accounts[0], gasLimit: '10000000' });
console.log(interface);
console.log('--------------------------------------------------------------------------------------------------------');
console.log(`The contract was successfully deployed to: ${result.options.address}`);
provider.engine.stop();
};
deploy();
Please make sure you use your own MetaMask private key and Infura API key.
Testing Deployment of the Smart Contract with Mocha
Let us now deploy the lottery smart contract to see if everything’s going well. However, this is not final. We are now only performing a simulation of deployment with Mocha to test the contract and see if everything’s good to go.
- Start by creating a test directory in your project directory
- Create your test file named Lottery.test.js
- Make sure you have configured your package.json to allow Mocha for testing. If not, look for the “scripts” object and set the value for “test” as “mocha”
- To run the script, pass the command: npm run test
Lottery.test.js:
const assert = require('assert');
const ganache = require('ganache-cli');
const { beforeEach } = require('mocha');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require('../compile.js');
let lottery;
let accounts;
beforeEach(async () => {
accounts = await web3.eth.getAccounts()
lottery = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode })
.send({ from: accounts[0], gas: '300000' });
});
describe('Lottery', () => {
it('deploys a contract', () => {
assert.ok(lottery.options.address);
});
it('allows one account to enter', async () => {
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('.02', 'ether')
})
const players = await lottery.methods.getPlayers().call({
from: accounts[0]
})
assert.equal(accounts[0], players[0]);
assert.equal(1, players.length);
});
it('allows multiple account to enter', async () => {
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('.02', 'ether')
});
await lottery.methods.enter().send({
from: accounts[1],
value: web3.utils.toWei('.02', 'ether')
});
await lottery.methods.enter().send({
from: accounts[2],
value: web3.utils.toWei('.02', 'ether')
});
const players = await lottery.methods.getPlayers().call({
from: accounts[0]
})
assert.equal(accounts[0], players[0]);
assert.equal(accounts[1], players[1]);
assert.equal(accounts[2], players[2]);
assert.equal(3, players.length);
});
it('requires a min ETH to enter', async () => {
try {
await lottery.methods.enter().send({
from: accounts[0],
value: 200
});
assert(false); // purposefully hrows an error no matter what
} catch (error) {
assert(error); //
}
});
it('checks if only manager can pick winner', async () => {
try {
await lottery.methods.pickWinner().send({
from: accounts[1]
})
assert(false);
} catch (error) {
assert(error);
}
});
it('sends money to winner and resets lottery', async () => {
await lottery.methods.enter().send({
from: accounts[0],
value: web3.utils.toWei('2', 'ether')
})
const initialBalance = await web3.eth.getBalance(accounts[0]);
await lottery.methods.pickWinner().send({
from: accounts[0]
});
const finalBalance = await web3.eth.getBalance(accounts[0]);
const difference = finalBalance - initialBalance;
console.log(difference);
assert(difference > web3.utils.toWei('1.8', 'ether'));
});
it('checks if players array is empty', async () => {
const players = await lottery.methods.getPlayers().call({
from: accounts[0]
})
assert(players.length == 0);
});
});
Run the test:
$ npm run test
> [email protected] test
> mocha
Lottery
√ deploys a contract
√ allows one account to enter (601ms)
√ allows multiple account to enter (1184ms)
√ requires a min ETH to enter (225ms)
√ checks if only manager can pick winner (178ms)
1999953164000002000
√ sends money to winner and resets lottery (653ms)
√ checks if players array is empty (150ms)
7 passing (6s)
Perfect! We are successfully passing all the tests.
Deploying the Smart Contract on Rinkeby Testnet
Now, the final process is the simplest, just use the following command to deploy the smart contract on the Rinkeby Testnet.
$ node deploy.js
Attempting to deploy from account: 0x5bA36E8dc1b0b5236f0a7330e0B34B70258F4De5
[{"constant":true,"inputs":[],"name":"manager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pickWinner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getPlayers","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"enter","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"players","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
--------------------------------------------------------------------------------------------------------
The contract was successfully deployed to: 0xC1e6c54E1546f7D97Deda849167b91E15674B9bF
Awesome! The contract was successfully deployed and we have received the ABI (interface) in the terminal.
Frequently Asked Questions (FAQs)
What is MSG in Blockchain?
A message or message call is a way by which one smart contract can interact with another contract or EOA(Externally Owned Account). This can be considered an internal transaction and it involves the use of gas and other elements such as target, return data, source, and data payload.
What is the MSG address in Solidity?
The msg.sender is the address of an individual or contract address that called or initiated a function or created a transaction.
Is MSG sender address payable?
In Solidity, using msg.sender one can access the address of the sender of the message or transaction and is not payable by default. But if you want to receive Ether, you have to declare it as Payable using the Payable keyword before the variable name of the address type. This keyword is used to indicate that the address can receive Ether.
How do I convert MSG sender to address payable?
The msg.sender is of type address, but you can easily change it into an address payable type by passing it to the function payable() as an argument, for example – payable(msg.sender).
What is the difference between MSG sender and TX origin in Solidity?
The msg.sender is the address of an individual or contract called or initiated a function or created a transaction whereas the tx.origin is the address of EOA, which stands for externally ownder account, the address from where the transaction is originally initiated.
What is the difference between MSG sender and owner?
The owner is the address that deploys a contract to the blockchain whereas the sender is the address that initiates a transaction or function within the deployed contract.
What is the salary of Solidity developer?
According to some sources, the salary of an Indian Solidity developer varies from ₹5,00,000 to ₹10,00,000.
What are modifiers in Solidity?
Modifiers are those functions in Solidity that can modify other functions in a contract by imposing certain conditions.
What is an EVM in Blockchain?
The EVM stands for Ethereum Virtual Machine. It is considered a runtime environment that is used for executing smart contracts and processing transactions mainly on Ethereum blockchain.
Conclusion
In this Solidity tutorial, we have seen the step-by-step process of sending Ethereum to a message sender in Solidity. However it is important to note that the code may change over time as Solidity is a relatively new programming language and comes with update regularity, but the process will definitely be the same. We hope after reading this article you got the answer you’re looking for.
Read More: Error Testing Smart Contract in Solidity Ethereum
Reference
Solidity basics: what “msg.sender” stands for – Stack Overflow