mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #4321 from ethereum/contractConversion
[BREAKING] Disallow conversion between unrelated contract types.
This commit is contained in:
		
						commit
						ef269bf40d
					
				| @ -40,6 +40,7 @@ Breaking Changes: | ||||
|  * Type Checker: Disallow arithmetic operations for boolean variables. | ||||
|  * Type Checker: Disallow tight packing of literals. This was already the case in the experimental 0.5.0 mode. | ||||
|  * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. | ||||
|  * Type Checker: Disallow conversions between unrelated contract types. Explicit conversion via ``address`` can still achieve it. | ||||
|  * Type Checker: Disallow empty tuple components. This was partly already the case in the experimental 0.5.0 mode. | ||||
|  * Type Checker: Disallow multi-variable declarations with mismatching number of values. This was already the case in the experimental 0.5.0 mode. | ||||
|  * Type Checker: Disallow specifying base constructor arguments multiple times in the same inheritance hierarchy. This was already the case in the experimental 0.5.0 mode. | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| .. index:: ! contract | ||||
| 
 | ||||
| .. _contracts: | ||||
| 
 | ||||
| ########## | ||||
| Contracts | ||||
| ########## | ||||
|  | ||||
| @ -379,7 +379,7 @@ In this example:: | ||||
|     } | ||||
| 
 | ||||
|     contract A { | ||||
|         address child; | ||||
|         B child; | ||||
| 
 | ||||
|         function test() public { | ||||
|             child = (new B).value(10)(); //construct a new B with 10 wei | ||||
|  | ||||
| @ -192,6 +192,23 @@ The ``.gas()`` option is available on all three methods, while the ``.value()`` | ||||
| .. note:: | ||||
|     The use of ``callcode`` is discouraged and will be removed in the future. | ||||
| 
 | ||||
| Contract Types | ||||
| -------------- | ||||
| 
 | ||||
| Every :ref:`contract<contracts>` defines its own type. Contracts can be implicitly converted | ||||
| to contracts they inherit from. They can be explicitly converted from and to ``address`` types. | ||||
| 
 | ||||
| The data representation of a contract is identical to that of the ``address`` type and | ||||
| this type is also used in the :ref:`ABI<ABI>`. | ||||
| 
 | ||||
| Contracts do not support any operators. | ||||
| 
 | ||||
| The members of contract types are the external functions of the contract including | ||||
| public state variables. | ||||
| 
 | ||||
| .. note:: | ||||
|     Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. | ||||
| 
 | ||||
| .. index:: byte array, bytes32 | ||||
| 
 | ||||
| 
 | ||||
| @ -884,7 +901,7 @@ for each ``_KeyType``, recursively. | ||||
|         function f() public returns (uint) { | ||||
|             MappingExample m = new MappingExample(); | ||||
|             m.update(100); | ||||
|             return m.balances(this); | ||||
|             return m.balances(address(this)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1403,15 +1403,15 @@ bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const | ||||
| { | ||||
| 	if (*this == _convertTo) | ||||
| 		return true; | ||||
| 	if (_convertTo.category() == Category::Integer) | ||||
| 		return dynamic_cast<IntegerType const&>(_convertTo).isAddress(); | ||||
| 	if (_convertTo.category() == Category::Contract) | ||||
| 	{ | ||||
| 		auto const& bases = contractDefinition().annotation().linearizedBaseContracts; | ||||
| 		if (m_super && bases.size() <= 1) | ||||
| 			return false; | ||||
| 		return find(m_super ? ++bases.begin() : bases.begin(), bases.end(), | ||||
| 					&dynamic_cast<ContractType const&>(_convertTo).contractDefinition()) != bases.end(); | ||||
| 		return find( | ||||
| 			m_super ? ++bases.begin() : bases.begin(), bases.end(), | ||||
| 			&dynamic_cast<ContractType const&>(_convertTo).contractDefinition() | ||||
| 		) != bases.end(); | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| @ -1420,8 +1420,7 @@ bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const | ||||
| { | ||||
| 	return | ||||
| 		isImplicitlyConvertibleTo(_convertTo) || | ||||
| 		_convertTo.category() == Category::Integer || | ||||
| 		_convertTo.category() == Category::Contract; | ||||
| 		_convertTo == IntegerType(160, IntegerType::Modifier::Address); | ||||
| } | ||||
| 
 | ||||
| bool ContractType::isPayable() const | ||||
|  | ||||
| @ -692,9 +692,9 @@ public: | ||||
| 	virtual Category category() const override { return Category::Contract; } | ||||
| 	explicit ContractType(ContractDefinition const& _contract, bool _super = false): | ||||
| 		m_contract(_contract), m_super(_super) {} | ||||
| 	/// Contracts can be implicitly converted to super classes and to addresses.
 | ||||
| 	/// Contracts can be implicitly converted only to base contracts.
 | ||||
| 	virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; | ||||
| 	/// Contracts can be converted to themselves and to integers.
 | ||||
| 	/// Contracts can only be explicitly converted to address types and base contracts.
 | ||||
| 	virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; | ||||
| 	virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; | ||||
| 	virtual std::string richIdentifier() const override; | ||||
|  | ||||
| @ -15,7 +15,7 @@ contract MultiSigWalletFactory is Factory { | ||||
|         public | ||||
|         returns (address wallet) | ||||
|     { | ||||
|         wallet = new MultiSigWallet(_owners, _required); | ||||
|         wallet = address(new MultiSigWallet(_owners, _required)); | ||||
|         register(wallet); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,7 @@ contract MultiSigWalletWithDailyLimitFactory is Factory { | ||||
|         public | ||||
|         returns (address wallet) | ||||
|     { | ||||
|         wallet = new MultiSigWalletWithDailyLimit(_owners, _required, _dailyLimit); | ||||
|         wallet = address(new MultiSigWalletWithDailyLimit(_owners, _required, _dailyLimit)); | ||||
|         register(wallet); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -56,7 +56,7 @@ contract premium is module, safeMath { | ||||
|         require( dbAddress != address(0x00) ); | ||||
|         db = ptokenDB(dbAddress); | ||||
|         if ( ! forReplace ) { | ||||
|             require( db.replaceOwner(this) ); | ||||
|             require( db.replaceOwner(address(this)) ); | ||||
|             isICO = true; | ||||
|             icoAddr = icoContractAddr; | ||||
|             assert( genesisAddr.length == genesisValue.length ); | ||||
|  | ||||
| @ -259,7 +259,7 @@ contract schelling is module, announcementTypes, schellingVars { | ||||
|         db = schellingDB(_db); | ||||
|         super.registerModuleHandler(_moduleHandler); | ||||
|         if ( ! _forReplace ) { | ||||
|             require( db.replaceOwner(this) ); | ||||
|             require( db.replaceOwner(address(this)) ); | ||||
|         } | ||||
|     } | ||||
|     function configure(announcementType a, uint256 b) external returns(bool) { | ||||
|  | ||||
| @ -71,7 +71,7 @@ contract token is safeMath, module, announcementTypes { | ||||
|         exchangeAddress = exchangeContractAddress; | ||||
|         isICO = ! forReplace; | ||||
|         if ( ! forReplace ) { | ||||
|             require( db.replaceOwner(this) ); | ||||
|             require( db.replaceOwner(address(this)) ); | ||||
|             assert( genesisAddr.length == genesisValue.length ); | ||||
|             require( address(this).balance >= genesisAddr.length * 0.2 ether ); | ||||
|             for ( uint256 a=0 ; a<genesisAddr.length ; a++ ) { | ||||
|  | ||||
| @ -54,7 +54,7 @@ contract Event { | ||||
|         public | ||||
|     { | ||||
|         // Transfer collateral tokens to events contract | ||||
|         require(collateralToken.transferFrom(msg.sender, this, collateralTokenCount)); | ||||
|         require(collateralToken.transferFrom(msg.sender, address(this), collateralTokenCount)); | ||||
|         // Issue new outcome tokens to sender | ||||
|         for (uint8 i = 0; i < outcomeTokens.length; i++) | ||||
|             outcomeTokens[i].issue(msg.sender, collateralTokenCount); | ||||
|  | ||||
| @ -102,12 +102,12 @@ contract Campaign { | ||||
|         timedTransitions | ||||
|         atStage(Stages.AuctionStarted) | ||||
|     { | ||||
|         uint raisedAmount = eventContract.collateralToken().balanceOf(this); | ||||
|         uint raisedAmount = eventContract.collateralToken().balanceOf(address(this)); | ||||
|         uint maxAmount = funding.sub(raisedAmount); | ||||
|         if (maxAmount < amount) | ||||
|             amount = maxAmount; | ||||
|         // Collect collateral tokens | ||||
|         require(eventContract.collateralToken().transferFrom(msg.sender, this, amount)); | ||||
|         require(eventContract.collateralToken().transferFrom(msg.sender, address(this), amount)); | ||||
|         contributions[msg.sender] = contributions[msg.sender].add(amount); | ||||
|         if (amount == maxAmount) | ||||
|             stage = Stages.AuctionSuccessful; | ||||
| @ -138,7 +138,7 @@ contract Campaign { | ||||
|         returns (Market) | ||||
|     { | ||||
|         market = marketFactory.createMarket(eventContract, marketMaker, fee); | ||||
|         require(eventContract.collateralToken().approve(market, funding)); | ||||
|         require(eventContract.collateralToken().approve(address(market), funding)); | ||||
|         market.fund(funding); | ||||
|         stage = Stages.MarketCreated; | ||||
|         emit MarketCreation(market); | ||||
| @ -156,7 +156,7 @@ contract Campaign { | ||||
|         market.close(); | ||||
|         market.withdrawFees(); | ||||
|         eventContract.redeemWinnings(); | ||||
|         finalBalance = eventContract.collateralToken().balanceOf(this); | ||||
|         finalBalance = eventContract.collateralToken().balanceOf(address(this)); | ||||
|         stage = Stages.MarketClosed; | ||||
|         emit MarketClosing(); | ||||
|     } | ||||
|  | ||||
| @ -60,8 +60,8 @@ contract StandardMarket is Market { | ||||
|         atStage(Stages.MarketCreated) | ||||
|     { | ||||
|         // Request collateral tokens and allow event contract to transfer them to buy all outcomes | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, this, _funding) | ||||
|                 && eventContract.collateralToken().approve(eventContract, _funding)); | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, address(this), _funding) | ||||
|                 && eventContract.collateralToken().approve(address(eventContract), _funding)); | ||||
|         eventContract.buyAllOutcomes(_funding); | ||||
|         funding = _funding; | ||||
|         stage = Stages.MarketFunded; | ||||
| @ -76,7 +76,7 @@ contract StandardMarket is Market { | ||||
|     { | ||||
|         uint8 outcomeCount = eventContract.getOutcomeCount(); | ||||
|         for (uint8 i = 0; i < outcomeCount; i++) | ||||
|             require(eventContract.outcomeTokens(i).transfer(creator, eventContract.outcomeTokens(i).balanceOf(this))); | ||||
|             require(eventContract.outcomeTokens(i).transfer(creator, eventContract.outcomeTokens(i).balanceOf(address(this)))); | ||||
|         stage = Stages.MarketClosed; | ||||
|         emit MarketClosing(); | ||||
|     } | ||||
| @ -88,7 +88,7 @@ contract StandardMarket is Market { | ||||
|         isCreator | ||||
|         returns (uint fees) | ||||
|     { | ||||
|         fees = eventContract.collateralToken().balanceOf(this); | ||||
|         fees = eventContract.collateralToken().balanceOf(address(this)); | ||||
|         // Transfer fees | ||||
|         require(eventContract.collateralToken().transfer(creator, fees)); | ||||
|         emit FeeWithdrawal(fees); | ||||
| @ -112,8 +112,8 @@ contract StandardMarket is Market { | ||||
|         // Check cost doesn't exceed max cost | ||||
|         require(cost > 0 && cost <= maxCost); | ||||
|         // Transfer tokens to markets contract and buy all outcomes | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, this, cost) | ||||
|                 && eventContract.collateralToken().approve(eventContract, outcomeTokenCost)); | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, address(this), cost) | ||||
|                 && eventContract.collateralToken().approve(address(eventContract), outcomeTokenCost)); | ||||
|         // Buy all outcomes | ||||
|         eventContract.buyAllOutcomes(outcomeTokenCost); | ||||
|         // Transfer outcome tokens to buyer | ||||
| @ -142,7 +142,7 @@ contract StandardMarket is Market { | ||||
|         // Check profit is not too low | ||||
|         require(profit > 0 && profit >= minProfit); | ||||
|         // Transfer outcome tokens to markets contract to sell all outcomes | ||||
|         require(eventContract.outcomeTokens(outcomeTokenIndex).transferFrom(msg.sender, this, outcomeTokenCount)); | ||||
|         require(eventContract.outcomeTokens(outcomeTokenIndex).transferFrom(msg.sender, address(this), outcomeTokenCount)); | ||||
|         // Sell all outcomes | ||||
|         eventContract.sellAllOutcomes(outcomeTokenProfit); | ||||
|         // Transfer profit to seller | ||||
| @ -164,11 +164,11 @@ contract StandardMarket is Market { | ||||
|         returns (uint cost) | ||||
|     { | ||||
|         // Buy all outcomes | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, this, outcomeTokenCount) | ||||
|                 && eventContract.collateralToken().approve(eventContract, outcomeTokenCount)); | ||||
|         require(   eventContract.collateralToken().transferFrom(msg.sender, address(this), outcomeTokenCount) | ||||
|                 && eventContract.collateralToken().approve(address(eventContract), outcomeTokenCount)); | ||||
|         eventContract.buyAllOutcomes(outcomeTokenCount); | ||||
|         // Short sell selected outcome | ||||
|         eventContract.outcomeTokens(outcomeTokenIndex).approve(this, outcomeTokenCount); | ||||
|         eventContract.outcomeTokens(outcomeTokenIndex).approve(address(this), outcomeTokenCount); | ||||
|         uint profit = this.sell(outcomeTokenIndex, outcomeTokenCount, minProfit); | ||||
|         cost = outcomeTokenCount - profit; | ||||
|         // Transfer outcome tokens to buyer | ||||
|  | ||||
| @ -95,14 +95,14 @@ contract FutarchyOracle is Oracle { | ||||
|         isCreator | ||||
|     { | ||||
|         // Buy all outcomes | ||||
|         require(   categoricalEvent.collateralToken().transferFrom(creator, this, funding) | ||||
|                 && categoricalEvent.collateralToken().approve(categoricalEvent, funding)); | ||||
|         require(   categoricalEvent.collateralToken().transferFrom(creator, address(this), funding) | ||||
|                 && categoricalEvent.collateralToken().approve(address(categoricalEvent), funding)); | ||||
|         categoricalEvent.buyAllOutcomes(funding); | ||||
|         // Fund each market with outcome tokens from categorical event | ||||
|         for (uint8 i = 0; i < markets.length; i++) { | ||||
|             Market market = markets[i]; | ||||
|             // Approve funding for market | ||||
|             require(market.eventContract().collateralToken().approve(market, funding)); | ||||
|             require(market.eventContract().collateralToken().approve(address(market), funding)); | ||||
|             market.fund(funding); | ||||
|         } | ||||
|         emit FutarchyFunding(funding); | ||||
| @ -122,7 +122,7 @@ contract FutarchyOracle is Oracle { | ||||
|         market.withdrawFees(); | ||||
|         // Redeem collateral token for winning outcome tokens and transfer collateral tokens to creator | ||||
|         categoricalEvent.redeemWinnings(); | ||||
|         require(categoricalEvent.collateralToken().transfer(creator, categoricalEvent.collateralToken().balanceOf(this))); | ||||
|         require(categoricalEvent.collateralToken().transfer(creator, categoricalEvent.collateralToken().balanceOf(address(this)))); | ||||
|         emit FutarchyClosing(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -92,7 +92,7 @@ contract UltimateOracle is Oracle { | ||||
|         // There was no challenge yet or the challenge period expired | ||||
|         require(   !isChallenged() | ||||
|                 && !isChallengePeriodOver() | ||||
|                 && collateralToken.transferFrom(msg.sender, this, challengeAmount)); | ||||
|                 && collateralToken.transferFrom(msg.sender, address(this), challengeAmount)); | ||||
|         outcomeAmounts[msg.sender][_outcome] = challengeAmount; | ||||
|         totalOutcomeAmounts[_outcome] = challengeAmount; | ||||
|         totalAmount = challengeAmount; | ||||
| @ -113,7 +113,7 @@ contract UltimateOracle is Oracle { | ||||
|         // Outcome is challenged and front runner period is not over yet and tokens can be transferred | ||||
|         require(   isChallenged() | ||||
|                 && !isFrontRunnerPeriodOver() | ||||
|                 && collateralToken.transferFrom(msg.sender, this, amount)); | ||||
|                 && collateralToken.transferFrom(msg.sender, address(this), amount)); | ||||
|         outcomeAmounts[msg.sender][_outcome] = outcomeAmounts[msg.sender][_outcome].add(amount); | ||||
|         totalOutcomeAmounts[_outcome] = totalOutcomeAmounts[_outcome].add(amount); | ||||
|         totalAmount = totalAmount.add(amount); | ||||
|  | ||||
| @ -31,8 +31,8 @@ contract Bounty is PullPayment, Destructible { | ||||
|    */ | ||||
|   function createTarget() public returns(Target) { | ||||
|     Target target = Target(deployContract()); | ||||
|     researchers[target] = msg.sender; | ||||
|     emit TargetCreated(target); | ||||
|     researchers[address(target)] = msg.sender; | ||||
|     emit TargetCreated(address(target)); | ||||
|     return target; | ||||
|   } | ||||
| 
 | ||||
| @ -47,7 +47,7 @@ contract Bounty is PullPayment, Destructible { | ||||
|    * @param target contract | ||||
|    */ | ||||
|   function claim(Target target) public { | ||||
|     address researcher = researchers[target]; | ||||
|     address researcher = researchers[address(target)]; | ||||
|     if (researcher == address(0)) { | ||||
|       revert(); | ||||
|     } | ||||
|  | ||||
| @ -26,7 +26,7 @@ contract TokenDestructible is Ownable { | ||||
|     // Transfer tokens to owner | ||||
|     for(uint256 i = 0; i < tokens.length; i++) { | ||||
|       ERC20Basic token = ERC20Basic(tokens[i]); | ||||
|       uint256 balance = token.balanceOf(this); | ||||
|       uint256 balance = token.balanceOf(address(this)); | ||||
|       token.transfer(owner, balance); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -28,7 +28,7 @@ contract HasNoTokens is Ownable { | ||||
|    */ | ||||
|   function reclaimToken(address tokenAddr) external onlyOwner { | ||||
|     ERC20Basic tokenInst = ERC20Basic(tokenAddr); | ||||
|     uint256 balance = tokenInst.balanceOf(this); | ||||
|     uint256 balance = tokenInst.balanceOf(address(this)); | ||||
|     tokenInst.transfer(owner, balance); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -33,7 +33,7 @@ contract TokenTimelock { | ||||
|     require(msg.sender == beneficiary); | ||||
|     require(now >= releaseTime); | ||||
| 
 | ||||
|     uint amount = token.balanceOf(this); | ||||
|     uint amount = token.balanceOf(address(this)); | ||||
|     require(amount > 0); | ||||
| 
 | ||||
|     token.transfer(beneficiary, amount); | ||||
|  | ||||
| @ -9420,7 +9420,7 @@ BOOST_AUTO_TEST_CASE(failed_create) | ||||
| 		contract C { | ||||
| 			uint public x; | ||||
| 			constructor() public payable {} | ||||
| 			function f(uint amount) public returns (address) { | ||||
| 			function f(uint amount) public returns (D) { | ||||
| 				x++; | ||||
| 				return (new D).value(amount)(); | ||||
| 			} | ||||
| @ -9428,7 +9428,7 @@ BOOST_AUTO_TEST_CASE(failed_create) | ||||
| 				if (depth < 1024) | ||||
| 					return this.stack(depth - 1); | ||||
| 				else | ||||
| 					return f(0); | ||||
| 					return address(f(0)); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| @ -12524,10 +12524,10 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) | ||||
| 				return (new C()).f(); | ||||
| 			} | ||||
| 			function fview() public returns (uint) { | ||||
| 				return (CView(new C())).f(); | ||||
| 				return (CView(address(new C()))).f(); | ||||
| 			} | ||||
| 			function fpure() public returns (uint) { | ||||
| 				return (CPure(new C())).f(); | ||||
| 				return (CPure(address(new C()))).f(); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
|  | ||||
| @ -3,11 +3,11 @@ | ||||
| contract B { | ||||
| 	A a; | ||||
| 	constructor() public { | ||||
| 		a = new A(this); | ||||
| 		a = new A(address(this)); | ||||
| 	} | ||||
| } | ||||
| contract A { | ||||
| 	constructor(address a) internal {} | ||||
| 	constructor(address) internal {} | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (141-146): Contract with internal constructor cannot be created directly. | ||||
|  | ||||
| @ -3,9 +3,9 @@ contract A { | ||||
|     } | ||||
| } | ||||
| contract B { | ||||
|     constructor(address) public { | ||||
|     constructor(C) public { | ||||
|     } | ||||
|     function b(address) public returns (A) { | ||||
|     function b(C) public returns (A) { | ||||
|         return new A(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,6 @@ | ||||
| contract C { | ||||
|   function f() public pure returns (C c) { | ||||
|     c = C(address(2)); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     C c = address(2); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-62): Type address is not implicitly convertible to expected type contract C. | ||||
| @ -0,0 +1,7 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address a = address(this); | ||||
|     a; | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,8 @@ | ||||
| contract C { | ||||
|   function f() public view { | ||||
|     address a = this; | ||||
|     a; | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (46-62): Type contract C is not implicitly convertible to expected type address. | ||||
							
								
								
									
										9
									
								
								test/libsolidity/syntaxTests/types/contract_to_base.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/libsolidity/syntaxTests/types/contract_to_base.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| contract A {} | ||||
| contract B is A {} | ||||
| contract C { | ||||
|   function f() public { | ||||
|     A a = new B(); | ||||
|     a; | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
							
								
								
									
										10
									
								
								test/libsolidity/syntaxTests/types/contract_to_base_base.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/libsolidity/syntaxTests/types/contract_to_base_base.sol
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| contract A {} | ||||
| contract B is A {} | ||||
| contract C is B {} | ||||
| contract D { | ||||
|   function f() public { | ||||
|     A a = new C(); | ||||
|     a; | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,9 @@ | ||||
| contract B {} | ||||
| contract A is B {} | ||||
| contract C { | ||||
|   function f() public pure { | ||||
|     A a = A(new B()); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (85-95): Explicit type conversion not allowed from "contract B" to "contract A". | ||||
| @ -0,0 +1,9 @@ | ||||
| contract A {} | ||||
| contract B {} | ||||
| contract C { | ||||
|   function f() public pure { | ||||
|     B b = B(new A()); | ||||
|   } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (80-90): Explicit type conversion not allowed from "contract A" to "contract B". | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user