KoreanFoodie's Study
Solidity 튜토리얼 #2 : 기본 문법 추가 본문
크립토 좀비에서 제공하는 튜토리얼을 통해 배우는 Solidity 문법을 정리하고 있습니다!
이전 게시글에서 작성했던 코드를 조금 확장해서, 좀비를 생성하는 것 말고도 다른 여러 가지 기능을 추가적으로 구현했다. 다른 개체를 먹고 다른 개체의 dna 와 섞인 새로운 좀비를 생성하거나, cryptokitty 의 dna 를 불러와서 좀비를 만들어보는 등의 함수가 구현되어 있다.
편의를 위해, 코드를 zombiefactory.sol 과 zombiefeeding.sol 로 나누었다.
이번 장을 정리한 내용은 다음과 같다.
1. Ethereum blockchaing 은 accounts 로 이루어져 있고, 각 accounts 에는 address 가 있다.
2. mapping 을 통해 C++ 에서의 map 같은 기능을 활용할 수 있다.
mapping (address => uint) public accountbalance;
3. msg.sender 라는, 모든 함수에서 접근 가능한 전역 변수가 있다.
msg.sender 는 해당 함수를 호출하는 사람(혹은 smart contract)의 address 를 나타낸다.
4. require 문을 통해, C++ 에서의 assert 같은 기능을 구현할 수 있다.
// Solidity 는 string 비교가 안되어 hash 값을 비교한다
require(keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked("Vitalik")));
5. 상속을 통해 기반 클래스의 변수와 메서드를 활용할 수 있다.
contract Doge {
function catchphrase() public returns (string memory) {
return "So Wow CryptoDoge";
}
}
contract BabyDoge is Doge {
function anotherCatchphrase() public returns (string memory) {
return "Such Moon BabyDoge";
}
}
6. import 를 이용해 다른 .sol 파일을 불러올 수 있다.
import "./someothercontract.sol";
7. 변수를 저장하는 장소는 storage 와 memory 가 있다.
storage 는 블록체인에 영구히 저장되고, memory 는 임시적으로 생성되는 지역 변수 같은 개념이다. hard disk 와 ram 의 차이라고 보면 편하다.
일반적으로 solidity 가 알아서 storage 인지 memory 인지 구분을 해 주지만, 해당 키워드를 사용해야 할 때도 있다.
contract SandwichFactory {
struct Sandwich {
string name;
string status;
}
Sandwich[] sandwiches;
function eatSandwich(uint _index) public {
// Sandwich mySandwich = sandwiches[_index];
// ^ Seems pretty straightforward, but solidity will give you a warning
// telling you that you should explicitly declare `storage` or `memory` here.
// So instead, you should declare with the `storage` keyword, like:
Sandwich storage mySandwich = sandwiches[_index];
// ...in which case `mySandwich` is a pointer to `sandwiches[_index]`
// in storage, and...
mySandwich.status = "Eaten!";
// ...this will permanently change `sandwiches[_index]` on the blockchain.
// If you just want a copy, you can use `memory`:
Sandwich memory anotherSandwich = sandwiches[_index + 1];
// ...in which case `anotherSandwich` will simply be a copy of the
// data in memory, and...
anotherSandwich.status = "Eaten!";
// ...will just modify the temporary variable and have no effect
// on `sandwiches[_index + 1]`. But you can do this:
sandwiches[_index + 1] = anotherSandwich;
// ...if you want to copy the changes back into blockchain storage.
}
}
8. 함수 접근 지정자에는 public 과 private 말고도, 추가적으로 interanl 과 external 이 존재한다.
- internal : private 과 같지만, 해당 contract 를 상속받은 contract 에서도 접근 가능
- external : public 과 같지만, 해당 contract '외부에서만' 호출 가능
9. Solidity 에서 interface 는 다음과 같이 사용한다.
// 인터페이스 정의
contract NumberInterface {
function getNum(address _myAddress) public view returns (uint);
}
// 정의한 인터페이스를 실제 contract 의 주소와 연결해서 사용한다
contract MyContract {
address NumberInterfaceAddress = 0xab38...
// ^ The address of the FavoriteNumber contract on Ethereum
NumberInterface numberContract = NumberInterface(NumberInterfaceAddress);
// Now `numberContract` is pointing to the other contract
function someFunction() public {
// Now we can call `getNum` from that contract:
uint num = numberContract.getNum(msg.sender);
// ...and do something with `num` here
}
}
10. Solidity 는 여러 개의 변수를 동시에 return 할 수 있다.
function multipleReturns() internal returns(uint a, uint b, uint c) {
return (1, 2, 3);
}
function processMultipleReturns() external {
uint a;
uint b;
uint c;
// This is how you do multiple assignment:
(a, b, c) = multipleReturns();
}
// Or if we only cared about one of the values:
function getLastReturnValue() external {
uint c;
// We can just leave the other fields blank:
(,,c) = multipleReturns();
}
위의 내용을 종합한 전체 코드는 다음과 같다!
zombiefactory.sol
pragma solidity >=0.5.0 <0.6.0;
contract ZombieFactory {
event NewZombie(uint zombieId, string name, uint dna);
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies;
mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount;
function _createZombie(string memory _name, uint _dna) internal {
uint id = zombies.push(Zombie(_name, _dna)) - 1;
zombieToOwner[id] = msg.sender;
ownerZombieCount[msg.sender]++;
emit NewZombie(id, _name, _dna);
}
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
function createRandomZombie(string memory _name) public {
require(ownerZombieCount[msg.sender] == 0);
uint randDna = _generateRandomDna(_name);
randDna = randDna - randDna % 100;
_createZombie(_name, randDna);
}
}
zombiefeeding.sol
pragma solidity >=0.5.0 <0.6.0;
import "./zombiefactory.sol";
contract KittyInterface {
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
}
contract ZombieFeeding is ZombieFactory {
address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
KittyInterface kittyContract = KittyInterface(ckAddress);
// Modify function definition here:
function feedAndMultiply(uint _zombieId, uint _targetDna, string memory _species) public {
require(msg.sender == zombieToOwner[_zombieId]);
Zombie storage myZombie = zombies[_zombieId];
_targetDna = _targetDna % dnaModulus;
uint newDna = (myZombie.dna + _targetDna) / 2;
// Add an if statement here
if (keccak256(abi.encodePacked(_species)) == keccak256(abi.encodePacked("kitty"))) {
newDna = newDna - newDna % 100 + 99;
}
_createZombie("NoName", newDna);
}
function feedOnKitty(uint _zombieId, uint _kittyId) public {
uint kittyDna;
(,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
// And modify function call here:
feedAndMultiply(_zombieId, kittyDna, "kitty");
}
}
'Tutorials > Solidity' 카테고리의 다른 글
Solidity 튜토리얼 #6 : Web3.js 와 이더리움 연동하기 (5) | 2022.09.23 |
---|---|
Solidity 튜토리얼 #5 : ERC721 과 SafeMath (0) | 2022.09.22 |
Solidity 튜토리얼 #4 : 이더리움 전송 및 payable 함수 (0) | 2022.09.22 |
Solidity 튜토리얼 #3 : 심화 문법 (0) | 2022.09.21 |
Solidity 튜토리얼 #1 : 기본 문법 (0) | 2022.09.20 |