728x90

 

이거 따라할 때 생겼던 에러와 해결내용

https://medium.com/pinata/how-to-build-erc-721-nfts-with-ipfs-e76a21d8f914

 

How to Build ERC-721 NFTs with IPFS

Using Open Zeppelin, Truffle, and Pinata

medium.com

 

1. ERC721

오픈제플린 최신버전은 ERC721URIStorage 가 ERC721를 대체한다. 이름 바꿔줘야함.

못가져옴 사용이 안되어서 에러 뜸

,DeclarationError: Undeclared identifier.
  --> project:/contracts/UniqueAsset.sol:29:3:
   |
29 |   _setTokenURI(newItemId, metadata);

 

//기존
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

//ERC721.sol가 없고 이제 ERC721URIStorage.sol이거 씀
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

 

 

 

근데 나는 여전히 계속 빨간줄 뜨더라고 그래서 

../node_modules/

로 경로 찾아주니까 빨간줄 사라짐

 

2. DeclarationError

사실 무엇보다

변수들을 못찾았는데

 

DeclarationError: Undeclared identifier. Did you mean "hash"?
  --> project:/contracts/UniqueAsset.sol:24:11:
   |
24 |   require(hashes[hash] != 1);
   |           ^^^^^^

,DeclarationError: Undeclared identifier. Did you mean "hash"?
  --> project:/contracts/UniqueAsset.sol:25:3:
   |
25 |   hashes[hash] = 1;
   |   ^^^^^^

그이유는!!!!

 

괄호를 잘못 묶었더라고..ㅋㅋㅋㅋ...

contract 안에 함수 있는건데 

contract랑 함수를 따로 해서 contract에 담아둔 애들이름 못 쓰는 거였다

 

 

 

결과 컴파일 잘된다!

 

3. 경고 Visibility for constructor is ignored.

 

경고 뜨는 건

 

  Warning: Visibility for constructor is ignored. If you want the contract to be non-deployable, 
making it "abstract" is sufficient.

(경고: 생성자의 가시성은 무시됩니다. 계약을 배포할 수 없도록 하려면 "추상"으로 만드는 것으로 충분합니다.)
  --> project:/contracts/UniqueAsset.sol:16:4:
   |
16 |    constructor() public ERC721("UniqueAsset", "UNA") {}
   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 

 

생성자에 더이상 가시성(public/ external)이 필요하지 않다고 한다.

왜냐면 생성자는 처음에 배포됐을 때만 읽히니까 다음에 또 불려질 일이 없다.

 

public을 지웠더니 경고가 사라졌다.

 

 

 

 

 

추가적으로는

솔리디티 버전을 코드랑 잘 맞춰줘야하는 것. 필요할 때 f1눌러서 버전수정했다.

 

 

 

 

따라한 내용 정리

필요한 것

  • vscode(nodejs, 솔리디티확장자)
  • IPFS 설치
  • Ganache — 이더리움의 로컬 블록체인 — 설치
  • 트러플 설치
  • NodeJS 설치
  • 피나타 API 키

스마트 계약 작성

 

(오픈제플린에서 가져와서 쓸거임)

 

새프로젝트 폴더 만듦

mkdir mySpecialAsset

디랙토리 초기화

npm init -y

 

Truffle을 활용해 스마트 계약 프로젝트 초기화

truffle init

Open Zeppelin 계약에 액세스할거라서 설치

npm install @openzeppelin/contracts

 

contracts 폴더 구조 안에 파일 생성! (솔리디티 버전 맞춰서 하기)

UniqueAsset.sol 

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "../node_modules/@openzeppelin/contracts/utils/Counters.sol";

contract UniqueAsset is ERC721URIStorage{
    //Counters to help us increment the identifiers for the tokens we mint.
    // 카운터 라이브러리(갯수세는역할함)를 쓴다. 이 유형으로
  using Counters for Counters.Counter;
    //변수만듦to keep track of all of the tokens we’ve issued.
  Counters.Counter private _tokenIds;
    //mapping for the IPFS hashes associated with tokens. 
  mapping(string => uint8) hashes;

   constructor() ERC721("UniqueAsset", "UNA") {}


// 특정IPFS해시에 아직 mint안되어있으면 mint하는 함수
// a method to our contract that will allow us to mint an NFT for a specific IPFS hash if not token has been minted yet for that hash
                           //nft수령인//NFT를 생성할 콘텐츠와 관련된 IPFS 해시 //자산에 대한 JSON 메타데이터에 대한 링크를 참조해야 한다
function awardItem(address recipient, string memory hash, string memory metadata) public returns (uint256)
{

  require(hashes[hash] != 1);
  hashes[hash] = 1;
  _tokenIds.increment();
  uint256 newItemId = _tokenIds.current();
  _mint(recipient, newItemId);
  _setTokenURI(newItemId, metadata);
  return newItemId;
}
}

폴더구조 migrations 들어가서 

2_deploy_contract.js

파일 생성

var UniqueAsset = artifacts.require("UniqueAsset");
module.exports = function (deployer) {
  deployer.deploy(UniqueAsset);
};

 

 

다 하면 컴파일

truffle compile

 

만약 오류가 발생하면 Ganache가 실행 중인 포트를 수동으로 설정 (아니면 나처럼 버전, 모듈경로 등의 문제일수도 있음 위에 참조)

truffle-config.js

(가나슈 퀵스타 누르면 뜨는 창에있는거랑 동일하게)

 

 

truffle migrate

이걸로 

 NFT 스마트 계약을 배포

 

 

 

이제 스마트 계약을 처리했으므로 기본 자산을 IPFS로 가져와 관련 NFT를 발행할 때 사용할 수 있는지 확인

 

 

IPFS에 자산 추가

우리는 Pinata를 사용하여 자산을 IPFS에 추가하고 고정된 상태로 유지하도록 할 것입니다.

https://app.pinata.cloud/pinmanager

 

uploadFile.js

업로드할 파일 준비

 

작업을

npm i axios form-data

쉽게 하려면 두 가지 종속성이 필요하다

 

이 스크립트에

const pinataApiKey = "YOURAPIKEY";
const pinataSecretApiKey = "YOURSECRETKEY";
const axios = require("axios");
const fs = require("fs");
const FormData = require("form-data");
const pinFileToIPFS = async () => {
  const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;=
  let data = new FormData();
  data.append("file", fs.createReadStream("./pathtoyourfile.png"));
  const res = await axios.post(url, data, {
    maxContentLength: "Infinity", 
    headers: {
      "Content-Type": `multipart/form-data; boundary=${data._boundary}`
      pinata_api_key: pinataApiKey, 
      pinata_secret_api_key: pinataSecretApiKey,
    },
  });
  console.log(res.data);
};
pinFileToIPFS();

 

코드 넣기 

Pinata에서 로그인하고 새 키 만들면 뜨는

"YOURAPIKEY"와 비밀키"YOURSECRETKEY"를 넣기 

 

 

node uploadFile.js

성공적으로 됐으면 이렇게 뜸

 

 

 

해당 해시는 자산의 검증 가능한 표현이고 IPFS 네트워크의 자산을 의미한다. 누군가가 자산을 변조하고 변경한 경우 해시가 달라진다. 이 해시는 우리의 스마트 계약을 통해 NFT를 발행할 때 사용해야 하는 것이다. 공개 게이트웨이를 제공하는 모든 IPFS 호스트는 이제 콘텐츠를 표시할 수 있다.. 라고 위 링크 글에 있다.

 

이게 Pinata에 자산을 업로드 하는 거라는데 pinata 내 계정에는 뭔가 달라진게 안보인다.

게이트웨이를 통해서 봐야돼서 그런건가 흠...

 

 

이상

뒤에 json 파일 만드는 것 이전까지 해봤다.

 

 

 

 

 

https://stackoverflow.com/questions/68608281/file-import-callback-not-supported-on-truffle-migrate

 

File import callback not supported on truffle migrate

I have a truffle project with the following contract (elided) that I'm running with truffle migrate: 1 pragma solidity >=0.6.0; 2 3 // implements the ERC721 standard 4 import &qu...

stackoverflow.com

 

 

 

https://forum.openzeppelin.com/t/function-settokenuri-in-erc721-is-gone-with-pragma-0-8-0/5978/21?page=2 

 

Function _setTokenURI() in ERC721 is gone with pragma ^0.8.0

I have the same error, now it’s OK: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract HarddiskCafe is ERC72

forum.openzeppelin.com

 

728x90
728x90

Exiting: Review successful transactions manually by checking the transaction hashes above on Etherscan.

Error:  *** Deployment Failed ***
"Migrations" -- Returned error: ENOENT: no such file or directory

 

아까는 배포가 되었다가 안됐던 이유가

가나슈 네트워크 연결한 7545에서 테스트넷(Ropsten테스트 네트워크로 하면된다길래..) 해보겠다고 다른거로 바꿔놔서 그랬다.

network7545내가 만든네트워크임

 

배포명령어가 좀 다르긴한대 비슷비슷하네 명령어 정리 해보자

truffle migrate --network development

아까는 명령어 문제인가 싶어서 위에 껄로 하긴 했는데 이건상관없는 거였음( truffle migrate 평소대로 이거해도같음)

 

 

명령어

//truffle프로젝트 초기화
truffle init

//각 네트워크에 배포된 컨트랙트의 주소표시
truffle networks

//컨트랙트 배포
truffle deploy

//개발모드로 접속(ganache-cli실행)
truffle develop

//모든 명령목록, 특정명령에 대한 정보를 표시
truffle help

배포

 truffle migrate

재배포시 

 truffle migrate --reset

 

 

(truffle deploy is an alias for truffle migrate. They both do the same thing.

별칭같은 거래 둘이 같대.)

728x90
728x90

truffle migrate시에 

payable 부분에서 오류가 나서 참고를 하려고 했지만

 

팀원한테 물어보니 payable이 truffle버전 5이상부터 된다는 얘기를 해서 (하지만 관련문서를 찾아봐도 잘안나온다 솔리디티 버전에 관한 얘기는 있는데 "address payable not supported in solc 0.4.x or earlier." 나는 solc버전이 0.8이었어서...)

npm uninstall -g truffle 하고

npm i g truffle@5.5.0

로 다시 까니까 됐다.

 

 

 

 

 

 

(packagelock json이 이런거 통일시켜주는 애려나? 근데 그거 있으면 npm i 모듈 깔때 에러 떠서 삭제하고 하는데 흠...)

 

 

728x90
728x90

설명출처: https://www.youtube.com/watch?v=NnZ0KOy2yJY&list=PLJQKWHLhBrxI43w0DU4uQrhWv4Pm1OFlx&index=37 

 

특징

1. 송금하기

2. 외부 스마트컨트랙 함수 부르기

3. 가변적인 gas

4. 이스탄불 하드포크, call 사용권장 가스가격 상승해서

5. re-entrancy 재진입

 

call vs Delegate call

 

 

Delegate call:

1. msg.sender가 본래의 스마트 컨트랙 사용자를 나타낸다.

2. delegate call이 정의된 스마트 컨트랙(즉 caller)이 외부 컨트랙의 함수들dmf 마치 자신의 것처럼 사용하고

(실질적인 값도 caller에 저장된다)

 

조건 

외부 스마트컨트랙과 caller 스마트컨트랙은 같은 변수를 갖고 있어야한다

 

 

 

 

 

 

블록체인 특성상 이미 배포된 코드를 수정할 수 없다.

Delegate Call를 사용하면 B코드에 적힌 코드로 적립된 포인트가 A에 저장된다.

그래서 스마트컨트랙B 기존꺼를 끊고 새로운 스마트컨트랙B2를 이어준다.

 

 

728x90
728x90

payable 이더를 받을때나 보낼때 쓰는 키워드

 

 

 

payable을 생성자에 넣을 때

 

 

생성자에 페이어블 넣으면 배포했을 때 생성자함수도 구현돼서 이더를 보낼수 있대

 

저 이더에 5넣고 배포 누르니까 빠져나감

 

 

 

특정계정 권한주기

 

 

modifier로 함수들에 조건 추가

 

 

 

 

강의: 인프런 솔리디티 깨부수기

728x90
728x90

주소.balance    주소의 현재 갖고 있는 이더의 잔액

( msg.value       송금액을 의미한다 달라! )

msg.sender      스마트컨트랙을 사용하는 주체, 보내는 자

주고 받는거 해봄

 

 

이더보내는 스마트컨트랙트 코드  (출처: https://github.com/D-One0914/BreakingSolidityBasic/blob/main/lec33.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0 < 0.9.0;

//주소.balance
//주소의 현재 갖고 있는 이더의 잔액을 의미함.  //  msg.value는 송금액을 의미한다 달라!

// msg.sender
// msg.sender는 스마트컨트랙을 사용하는 주체라고 볼 수 있다 
// 앞으로 설명할 call 과 delegate call에서 주요 내용이니 관심잇게 봐라

contract MobileBanking{
    event SendInfo(address _msgSender, uint256 _currentValue);
    event MyCurrentValue(address _msgSender,uint256 _value);
    event CurrentValueOfSomeone(address _msgSender, address _to, uint256 _value);


   //이더를 보낼라면 
   //을 넣을 줄 알았지만!!! 보내는 주소, 받을 사람 주소만 있음 되는구나.. 이더를 받아야되기때문에 payable써준다 //함수전체도 이더보는거라 payable써줌
    function sendEther(address payable _to) public payable {
        require (msg.sender.balance >= msg.value , "your balance is not enough");
        //트랜스퍼 함수를 통해 이더 송금
        _to.transfer(msg.value);
        //보낸 나의 주소, 내 잔고
         emit SendInfo(msg.sender, (msg.sender).balance);
    }
    //그냥 현재 잔고확인 함수인듯?
    function checkValueNow() public{
        emit MyCurrentValue(msg.sender, (msg.sender).balance);
    }
    //어떤 계정의 잔고 확인하고 싶을때, 확인하고 싶은 주소 넣기
    function checkUserValue(address _to) public{
       emit CurrentValueOfSomeone(msg.sender, _to, _to.balance);
    }

}

 

 

이더송금하기 

sendEther함수 사용

 

1. 코드를 컴파일한다

또는 우클릭해서 원하는 코드 컴파일.

 

2. ACCOUNT 에서 현재 내 계정주소 확인하고  Deploy 배포한다.

 

1로 표시한거 &gt;&nbsp; 계정주소 넣을 부분 2로 표시한거 &gt; 이더금액 넣는 부분 3로 표시한거 &gt;&nbsp; Deploy 배포 4로 표시한거 &gt; 함수사용하는 부분 5로 표시한거 &gt;&nbsp; 내역&nbsp; &nbsp; &nbsp; &nbsp;(숫자 이거 순서 아님주의!!!)

3. 함수 실행

 

Deploy했으면

Deployed Contracts 가 생성될거다.

함수에 값넣어서 이더송금할 수 있다.

 

sendEther는 송금받을 주소를 넣는 곳이다.

 

Account에서 보낼 주소를 골라서 복사해서 sendEther에 넣는다.

그리고 Account에서 다시 내 계정주소로 와있는지 확인한 다음에

보낼 이더 값을 Value에 넣는다. Ether로 되어있는지 확인한다.

그리고 sendEther를 눌러 송금함수를 실행한다. 

 

잘보내졌으면 저렇게 내역이 뜬다.

ACCOUNT 눌러서 남은 잔고와 받은 잔고를 맨위에 사진처럼 확인할 수 있다. 

 

 

 

 

현재계정 잔고확인하기

checkValueNow함수 사용

 

 

 

 

 

 

특정계정의 잔고 확인하기 

checkUserValue함수

에 _to 확인할 계정주소 넣고

원래 보낼 주소로 되어있는지 ACCOUNT확인하고

 

함수 실행하면

_msgSender 주체

_to 확인한 계정

_value 잔고

 

 

 

 

 

728x90
728x90

솔리디티 (이더리움 등 블록체인 플랫폼에서 스마트 계약 작성과 구현에 사용되는 계약 지향 프로그래밍 언어)

쓸 때 여기서 바로 할 수 있긴한데

https://remix.ethereum.org/

 

Remix - Ethereum IDE

 

remix.ethereum.org

 

vscode 비주얼 스튜디오에서 작업하고 싶으니까 작업 환경을 설정해보자

 

먼저 당연히 깔려있어야할

 

비주얼스튜디오 설치

Visual Studio Code

Node.js 설치

Node.js

NPM설치

npm   (Node Packaged Manager를 전역에 설치. npm install -g npm)

 

트러플 설치!!

npm install -g truffle

 

 

트러플은 이더리움 프레임워크로 소스코드를 쉽게 compile,deploy 작업을 할 수있게 해줌

 

설치했으면 버전확인하고

 

이제

비주얼 스튜디오에 Solidity 솔리디티 확장자를 설치할거임!

vscode 열고 Ctrl + Shift + X 누르거나 여기 누르면 솔리디티 검색해서 깔면 됨!

 

(파이썬도 깔아줘야한대서 깔긴했는데 왜까는지 모르겠음..내가 본 문서에서는 얘기 없어서)

 

 

암튼 이제 됐고

truffle init

 

하면 

이렇게 생겨남

이제 내가 작업할 솔리디티 파일을 

constracts에 넣으면 됨 

클립토 좀비에서 레슨1의 완성된 코드 하나 가져와서 만듦

코드 복붙해보면 

 

지금은 안뜨는데 아까는 

이렇게 버전이 안맞다고 떴었음

여기 들어가서 Set compiler version을 0.4.19로 맞춰줘.

 

근데 난 이게 안됐음

알고보니까 솔리디티 확장자가 최신버전이더라고 

거기서 버전을 맞춰줘야됐었음

톱니바퀴 눌러서 환경설정 들어가면

 

여기서 버전 설정해주면 빨간줄 사라짐!!

 

환경설정 끝~~

 

 

 

이제 버전 문제 해결됐으면

 

truffle develop

디벨롭하고

run & deploy 누르고 

Activate하기 

 

 

 

 

그럼 이거 켜짐 

연결안되어있으면 connect

그리고 compile 누르면

 

여기서부터는 잘모르겠음..

deploy 누르고 

call해보고 했는데 뭘하려고 하는지 이해못함

 

 

 

728x90
728x90

https://cryptozombies.io/ko/lesson

 

#1 Solidity Tutorial & Ethereum Blockchain Programming Course | CryptoZombies

CryptoZombies is The Most Popular, Interactive Solidity Tutorial That Will Help You Learn Blockchain Programming on Ethereum by Building Your Own Fun Game with Zombies — Master Blockchain Development with Web3, Infura, Metamask & Ethereum Smart Contracts

cryptozombies.io

내가 볼라고 적는거임

다들 클립토좀비 들어가서 공부해

 

레슨 1의

챕터 2: 컨트랙트

 

솔리디티 코드는 컨트랙트안에 싸여있음

 

솔리디티 소스 코드는 

버전선언으로 시작해야함!

 

pragma solidity ^0.4.19; //1. 여기에 솔리디티 버전 적기

//2. 여기에 컨트랙트 생성
contract ZombieFactory{
    
}

 

컨트랙트를 위한 뼈대 갖추기 완성!

 

챕터 3: 상태 변수 & 정수

상태변수는 컨트랙트 저장소에 영구적으로 저장돼!

즉 이더리움 블록체인에 기록된다는 것.

 

contract Example {
//이 변수가 블록체인에 영구적으로 저장됨
uint myUnsignedUnteger = 100;
}

 

챕터 4: 수학 연산

  • 덧셈: x + y
  • 뺄셈: x - y,
  • 곱셈: x * y
  • 나눗셈: x / y
  • 모듈로 / 나머지: x % y (이를테면, 13 % 5는 3이다. 왜냐면 13을 5로 나누면 나머지가 3이기 때문이다)

솔리디티는 지수 연산도 지원하지 (즉, "x의 y승", x^y이지):

uint x = 5 ** 2; // 즉, 5^2 = 25

챕터 5: 구조체

복잡한 자료형을 필요로 할 때 솔리디티로는 구조체를 쓰면 됨

struct Person {
uint age;
string name;
}

구조체를 통해 여러 특성가진 보다 복잡한 자료형을 생성할 수 있지.

 

 

컨트랙트 안에 구조체 있는 모습

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

}

챕터 6: 배열

어떤 것의 모음집이 필요할 때 

배열을 사용할 수 있지

 

솔리디티에도 정적배열, 동적배열  두 종류배열 있어. 

//2개의 원소를 담을 수 있는 고정길이의 배열;
uint[2] fixedArray;

//고정길이의 배열, 5개의 스트링을 담을 수 있다.
string[5] stringArray;

//동적배열은 고정된 크기가 없으며 계속 크기가 커질 수 있다.
uint[] dynamicArray;

 

구조체의 배열을 생성할 수 있다!

아까 우리가 sturct Person {uint age; string name;} 이렇게 만들었던 구조체를 이용하면 

Person[] people; // 이는 동적 배열로, 원소를 계속 추가할 수 있다.

상태변수가 블록체인에 영구적으로 저장할 수 있는 것처럼 구조체의 동적배열을 생성하면 

마치 데이터베이스처럼 컨트랙트에 구조화된 데이터를 저장하는데 유용하다. 

 

Public 배열

public으로 배열을 선언할 수 있음 솔리디티는 이런 배열을 위해 getter메소드를 자동적으로 생성한다. 

Person[] public people;

다른 컨트랙트들은 이 배열을 읽을 수는 있게되지만 쓸 수는 없다.

이는 컨트랙트에 공개데이터를 저장할 때 유용한 패턴이다.

 

 

 

 

지금까지 한 코드

pragma solidity ^0.4.19;

contract ZombieFactory {

    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {
        string name;
        uint dna;
    }

    // 좀비들을 다른 앱에 자랑하고 싶어서 좀비 군대 저장소를public으로 함.
    //Zombie구조체의 public배열을 생성하고 이름을 zombies로 한다.


    Zombie[] public zombies;

}

 

챕터 7: 함수 선언

솔리디티에서 함수 선언

function eatHam(string _name, uint _amount){
}

(함수의 인자명을 _로 시작하는 건 전역변수랑 구별하려고 하는 관례때문임~)

 

이 함수를 오출 할때는 이렇게 할 수 있겠지

eatHam("jun",100);

챕터 8: 구조체와 배열 활용하기

새로운 구조체를 생성하기 

 

전에 만들어 놓은 Person구조체를 사용할거야.

//구조체 Person 틀
struct Person {
  uint age;
  string name;
}
//Person배열을 peole로 이름지음
Person[] public people;

그 틀로 새로운 Person satoshi을 찍어낼거야. 

//Person틀쓸거고 변수명은 satoshi임  // age, name
Person satoshi = Person(172,"Satoshi");
//people배열에 이 사람을 추가한다.
peole.push(satoshi);

이 두 줄을 한 줄로 표현하면 이거임

people.push(Person(16,"Jun"));

 

 

챕터 9: Private / Public 함수

솔리디티에서 함수는 기본적으로 public으로 선언된다. 

누구나 또는 다른 어느 컨트랙트가 우리의 컨트랙트의 함수를 호출하고 코드를 실행할 수 있다는 의미다.

하지만 이건 공격에 취약해질 수 있는 가능성이 있어서 

기본적으로 함수는 private로 선언하고 공개할 함수만 public으로 선언하는 게 좋다

 

private함수를 선언하는 방법

unit[] numbers;
function _addToArray(uint _number) private {
numbers.push(_number);
}

private는 컨트랙트 내의 다른 함수들만이 이 함수를 호출해서 numbers 배열로 무언가를 추가할 수 있다걸 의미.

함수 인자명과 마찬가지로 private함수명도 언더바_로 시작하는 것이 관례임.

 

 

챕터 10: 함수 더 알아보기

함수의 반환값, 함수의 제어자

 

반환값

함수에서 어떤 값을 반환받으려면 다음과같이 선언해야함.

 

string greeting = "what's up dog";
function sayHello() public returns (string) {
//솔리디티에서 함수 선언은 반환값 종류를 포함한다. 지금은 string이야. 
return greeting;
}

함수제어자

위에 함수는 솔리디티에서 어떤값을 변경하거나 무언가를 쓰는등 상태를 변화시키지 않는다. 

이렇게 함수가 데이터를 보기만 하고 변경하지 않는 건 view함수로 선언한다.

function sayHello() public view returns (string) {
}

 

728x90

+ Recent posts