Account와 Trx의 구성요소 구분
Account {
nonce:
balance:
code:
storage:
}
Trx {
to:
value:
gas:
data: (ex:setName("~")
}
account의 경우 code와 storage의 내용에 따라 EOA와 CA가 구분된다.
Trx는 value와 data에 어떠한 내용이 들어있냐에 따라 어떠한 역할을 하는 트랜잭션인지가 구분된다.
contract에 함수를 입력할때 블록체인에 입력된 정보를 불러오는 데에는 view를 사용하고, 자신이 입력한 인수를 사용하여 계산등의 결과값을 돌려받을때는 pure를 사용한다. 그밖의 컨트랙트 안의 변수의 값을 변동시키거나 체인 변화를 일으킨다면 view나 pure가 사용되선 안되고, 이 경우 서명을 요구하기 때문에 만약 이 같은 함수를 실행시킨다면 일반적으로 연동된 네트워크에서 사용하고 있는 지갑의 서명 요청이 팝업된다.
ERC-20 토큰 컨트랙트 (토큰 규격의 일종)
pragma solidity >=0.4.22 <0.6.0;
contract ERC20Basic {
string public constant name = "name";
string public constant symbol = "ABC";
uint8 public constant decimals = 0;
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
event Transfer(address indexed from, address indexed to, uint tokens);
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_;
using SafeMath for uint256;
constructor(uint256 total) public {
totalSupply_ = total;
balances[msg.sender] = totalSupply_;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public view returns (uint) {
return balances[tokenOwner];
}
function transfer(address receiver, uint numTokens) public returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub(numTokens);
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] = balances[owner].sub(numTokens);
allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
}
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
symbol: 비트코인의 BTC와 같이 토큰의 약어를 표시
event: web의 경우 node.js에서 특정 프론트에서만 접근이 가능하도록 설정이 가능한데, contract의 경우 어디서나 접근이 가능한 환경이기 때문에, contract에서 어떠한 일들이 벌어지는지 확인해야할 필요가 있다. event를 통해 contract 내의 상황에 대한 관리, 감독이 가능하다.(?)
mapping: 위의 (address ⇒ uint) balance; 경우 balance라는 키와 값이 매칭되는 특정 공간을 창출하여 address가 key, unit을 value로 갖도록 한다.
constructor: 생성자로, contract를 배포할때 생성되며 숫자를 입력받으면 totalSupply 라는 공간을 만들어 놓고 해당 숫자를 totalSupply에 대입시킨다. 공간에 대입시키게 되면 balance에서 msg.sender 즉 배포자의 주소(키)를 찾아가서 그곳의 value에 다시 대입 시키게 된다. 예를 들어 100이라는 숫자를 입력하게 되면 배포자인 자신의 주소의 value값에 100이라는 숫자가 입력되는 방식이다.
transfer함수 : msg.sender의 balance를 입력한 numToken의 값과 비교하여 현재 balance가 크다면 numToken의 값만큼 빼고, receiver의 balance에 numToken의 값만큼 더해주는 방식으로 Transfer, 송금 함수를 진행하게 된다.
※ remix 좌측의 deploy를 통해 서명하고 contract를 배포할 경우 입력한 totalSupply 만큼의 symbol로 설정한 토큰이 생성되는 것이고 이러한 토큰은 계정간 전송을 해도 상대방의 account에는 변화가 없고, contract 배포자의 Trx에서만 변화가 생긴다.
즉 토큰의 전송은 코인 전송과 깉은 것이 아니고 일종의 컨트랙트 함수의 배포를 통해 Trx data부분에 변화를 준것으로 보면된다.

cf) Trx 해시주소는 EOA, CA의 해시주소보다 길다.
컨트랙트 상의 입력된 값의 변화일 뿐이다. 실제로 A의 account에서 B의 account로 토큰이라는 것이 이동되는 것보다는 컨트랙트가 트랜잭션의 내용에 따라 A와 B의 balance를 정리해주는 것일 뿐이다.
컨트랙트를 서명 후 배포할 경우 Trx의 data 부분에 compile된 bytecode(컨트랙트의 내용)가 들어가 있게된다. 만약 해당 bytecode 부분에 payable 속성이 없는데 배포할때 value 값에 무언가가 들어가 있다면 옳게 시행이 되지 않게된다. 컨트랙트의 배포는 compile의 과정을 거친 컨트랙트가 체인 상에 올라가게 되는 것을 의미하고, 배포시에도 배포자의 서명이 요구된다. 초기 배포시에만 설정할 수 있는 변수값들을 constructor 속성을 통해 미리 잘 설정해놓는 것이 중요하다.
배포된 컨트랙트내의 함수를 실행하는 것은 컨트랙트의 값을 읽는것일 수도 있고, 단순히 연산만 사용하는 것일 수도 있다. 이 두경우는 서명이 필요하지 않지만 만약 함수실행을 통해 어떠한 값에 변화를 주게 된다면 서명이 필요하고, 당연히 가스비가 요구된다.